@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
at recaptime-dev/main 113 lines 2.6 kB view raw
1<?php 2 3final class AphrontRequestStream extends Phobject { 4 5 private $encoding; 6 private $stream; 7 private $closed; 8 private $iterator; 9 10 public function setEncoding($encoding) { 11 $this->encoding = $encoding; 12 return $this; 13 } 14 15 public function getEncoding() { 16 return $this->encoding; 17 } 18 19 public function getIterator() { 20 if (!$this->iterator) { 21 $this->iterator = new PhutilStreamIterator($this->getStream()); 22 } 23 return $this->iterator; 24 } 25 26 public function readData() { 27 if (!$this->iterator) { 28 $iterator = $this->getIterator(); 29 $iterator->rewind(); 30 } else { 31 $iterator = $this->getIterator(); 32 } 33 34 if (!$iterator->valid()) { 35 return null; 36 } 37 38 $data = $iterator->current(); 39 $iterator->next(); 40 41 return $data; 42 } 43 44 private function getStream() { 45 if (!$this->stream) { 46 $this->stream = $this->newStream(); 47 } 48 49 return $this->stream; 50 } 51 52 private function newStream() { 53 $stream = fopen('php://input', 'rb'); 54 if (!$stream) { 55 throw new Exception( 56 pht( 57 'Failed to open stream "%s" for reading.', 58 'php://input')); 59 } 60 61 $encoding = $this->getEncoding(); 62 if ($encoding === 'gzip') { 63 // This parameter is magic. Values 0-15 express a time/memory tradeoff, 64 // but the largest value (15) corresponds to only 32KB of memory and 65 // data encoded with a smaller window size than the one we pass can not 66 // be decompressed. Always pass the maximum window size. 67 68 // Additionally, you can add 16 (to enable gzip) or 32 (to enable both 69 // gzip and zlib). Add 32 to support both. 70 $zlib_window = 15 + 32; 71 72 $ok = stream_filter_append( 73 $stream, 74 'zlib.inflate', 75 STREAM_FILTER_READ, 76 array( 77 'window' => $zlib_window, 78 )); 79 if (!$ok) { 80 throw new Exception( 81 pht( 82 'Failed to append filter "%s" to input stream while processing '. 83 'a request with "%s" encoding.', 84 'zlib.inflate', 85 $encoding)); 86 } 87 } 88 89 return $stream; 90 } 91 92 public static function supportsGzip() { 93 if (!function_exists('gzencode') || !function_exists('gzdecode')) { 94 return false; 95 } 96 97 $has_zlib = false; 98 99 // NOTE: At least locally, this returns "zlib.*", which is not terribly 100 // reassuring. We care about "zlib.inflate". 101 102 $filters = stream_get_filters(); 103 foreach ($filters as $filter) { 104 if (!strncasecmp($filter, 'zlib.', strlen('zlib.'))) { 105 $has_zlib = true; 106 break; 107 } 108 } 109 110 return $has_zlib; 111 } 112 113}