PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 16.1-beta
Jetpack – WP Security, Backup, Speed, & Growth v16.1-beta
16.1.1 16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / vendor / wp-php-toolkit / bytestream / ReadStream / class-basebytereadstream.php
jetpack / vendor / wp-php-toolkit / bytestream / ReadStream Last commit date
class-basebytereadstream.php 1 week ago class-deflatereadstream.php 1 week ago class-filereadstream.php 1 week ago class-inflatereadstream.php 1 week ago class-limitedbytereadstream.php 1 week ago class-transformedreadstream.php 1 week ago interface-bytereadstream.php 1 week ago
class-basebytereadstream.php
239 lines
1 <?php
2
3 namespace WordPress\ByteStream\ReadStream;
4
5 use WordPress\ByteStream\ByteStreamException;
6 use WordPress\ByteStream\NotEnoughDataException;
7
8 abstract class BaseByteReadStream implements ByteReadStream {
9
10 const CHUNK_SIZE_BYTES = 64 * 1024; // 64kb.
11
12 /**
13 * The maximum number of consumed bytes to keep in memory.
14 *
15 * For example:
16 *
17 * The quick brown fox jumps over the lazy dog.
18 * ^-------------------^
19 * consumed bytes
20 *
21 * Say the maximum lookbehind bytes is 4. Then the byte stream will forget about
22 * all consumed bytes except the last 4:
23 *
24 * fox jumps over the lazy dog.
25 * ^--^
26 * consumed but retained for seek()-ing backwards.
27 *
28 * @var int
29 */
30 protected $max_lookbehind_bytes = 2048;
31
32 /**
33 * The remaining unconsumed bytes.
34 *
35 * @var string
36 */
37 protected $buffer = '';
38
39 /**
40 * How many bytes have already been consumed in the current **buffer**.
41 *
42 * @var int
43 */
44 protected $offset_in_current_buffer = 0;
45
46 /**
47 * How many bytes have already been forgotten in the current **stream**.
48 *
49 * @var int
50 */
51 protected $bytes_already_forgotten = 0;
52
53 /**
54 * Whether the stream has been closed for reading.
55 *
56 * @var bool
57 */
58 protected $is_read_closed = false;
59
60 /**
61 * How many bytes are expected in the stream. Optional.
62 *
63 * When it's null, the stream is unbounded and length() will also return null.
64 *
65 * @var int|null
66 */
67 protected $expected_length = null;
68
69 public function length(): ?int {
70 return $this->expected_length;
71 }
72
73 public function pull( ?int $n = self::CHUNK_SIZE_BYTES, string $mode = self::PULL_NO_MORE_THAN ): int {
74 switch ( $mode ) {
75 case self::PULL_NO_MORE_THAN:
76 case self::PULL_EXACTLY:
77 break;
78 default:
79 throw new ByteStreamException( 'Invalid pull mode' );
80 }
81 if ( $this->is_read_closed ) {
82 throw new ByteStreamException( 'Cannot pull() on a closed producer' );
83 }
84
85 if ( 0 === $n ) {
86 return 0;
87 }
88
89 if ( $n < 0 ) {
90 throw new ByteStreamException( 'Cannot pull a negative number of bytes' );
91 }
92
93 if ( $n <= $this->count_consumable_bytes() ) {
94 return $n;
95 }
96
97 if ( $this->reached_end_of_data() ) {
98 if ( ByteReadStream::PULL_EXACTLY === $mode ) {
99 throw new NotEnoughDataException( 'End of data reached while pulling' );
100 }
101
102 return 0;
103 }
104
105 if ( ByteReadStream::PULL_NO_MORE_THAN === $mode ) {
106 return $this->pull_no_more_than( $n );
107 }
108
109 return $this->pull_exactly( $n );
110 }
111
112 protected function pull_exactly( $n ): int {
113 $empty_pulls = 0;
114 while ( $this->count_consumable_bytes() < $n ) {
115 $consumable_before = $this->count_consumable_bytes();
116 $this->pull_no_more_than( $n );
117 $consumable_after = $this->count_consumable_bytes();
118
119 if ( $consumable_after === $consumable_before ) {
120 ++$empty_pulls;
121 if ( $this->reached_end_of_data() ) {
122 throw new NotEnoughDataException( 'End of data reached while pulling' );
123 }
124 }
125
126 if ( $empty_pulls > 4 ) {
127 throw new NotEnoughDataException( '4 empty pulls in a row, we are probably at the end of the data' );
128 }
129 }
130
131 return $n;
132 }
133
134 protected function pull_no_more_than( $n ): int {
135 $this->buffer .= $this->internal_pull( self::CHUNK_SIZE_BYTES );
136
137 return min( $n, $this->count_consumable_bytes() );
138 }
139
140 public function consume_all(): string {
141 $body = '';
142 while ( true ) {
143 if ( $this->reached_end_of_data() ) {
144 return $body;
145 }
146 $consumable = $this->pull( self::CHUNK_SIZE_BYTES );
147 $body .= $this->consume( $consumable );
148 }
149 }
150
151 protected function count_consumable_bytes(): int {
152 return strlen( $this->buffer ) - $this->offset_in_current_buffer;
153 }
154
155 abstract protected function internal_pull( $n ): string;
156
157 public function peek( int $n ): string {
158 return substr( $this->buffer, $this->offset_in_current_buffer, $n );
159 }
160
161 public function consume( int $n ): string {
162 if ( strlen( $this->buffer ) < $this->offset_in_current_buffer + $n ) {
163 throw new NotEnoughDataException( 'Cannot consume more bytes than available in the buffer.' );
164 }
165 $bytes = substr( $this->buffer, $this->offset_in_current_buffer, $n );
166 $this->offset_in_current_buffer += $n;
167 if ( $this->offset_in_current_buffer > $this->max_lookbehind_bytes ) {
168 $overflow = $this->offset_in_current_buffer - $this->max_lookbehind_bytes;
169 $this->offset_in_current_buffer -= $overflow;
170 $this->bytes_already_forgotten += $overflow;
171 $this->buffer = substr( $this->buffer, $overflow );
172 }
173
174 return $bytes;
175 }
176
177 public function seek( int $target_offset ): void {
178 // We have that offset in the buffer, let's just update the pointer.
179 if ( $target_offset >= $this->bytes_already_forgotten && $target_offset <= $this->bytes_already_forgotten + strlen( $this->buffer ) ) {
180 $this->offset_in_current_buffer = $target_offset - $this->bytes_already_forgotten;
181
182 return;
183 }
184 if ( null !== $this->length() && $target_offset > $this->length() ) {
185 $length = $this->length();
186 throw new NotEnoughDataException(
187 esc_html(
188 sprintf(
189 'Cannot seek to past the stream length (seeked to %d, stream length is %d).',
190 $target_offset,
191 $length
192 )
193 )
194 );
195 }
196
197 if ( $target_offset < 0 ) {
198 throw new ByteStreamException( 'Cannot seek to a negative offset' );
199 }
200
201 // Seeking outside of buffer range, we need a producer-specific implementation.
202 $this->seek_outside_of_buffer( $target_offset );
203 }
204
205 protected function seek_outside_of_buffer( int $target_offset ): void {
206 throw new ByteStreamException( 'Cannot seek outside of the buffered range' );
207 }
208
209 public function tell(): int {
210 return $this->bytes_already_forgotten + $this->offset_in_current_buffer;
211 }
212
213 public function reached_end_of_data(): bool {
214 if ( $this->is_read_closed ) {
215 return true;
216 }
217 if ( $this->count_consumable_bytes() > 0 ) {
218 return false;
219 }
220 if ( null !== $this->length() ) {
221 return $this->tell() >= $this->length();
222 }
223
224 return $this->internal_reached_end_of_data();
225 }
226
227 protected function internal_reached_end_of_data(): bool {
228 return false;
229 }
230
231 public function close_reading(): void {
232 $this->is_read_closed = true;
233 $this->internal_close_reading();
234 }
235
236 protected function internal_close_reading(): void {
237 }
238 }
239