Skip to content

Commit f6f6152

Browse files
committed
stream: add filter seekable enum and other fixes
1 parent ecd7c90 commit f6f6152

File tree

8 files changed

+82
-83
lines changed

8 files changed

+82
-83
lines changed

ext/bz2/bz2_filter.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -189,13 +189,11 @@ static zend_result php_bz2_decompress_seek(
189189
int whence
190190
)
191191
{
192-
php_bz2_filter_data *data;
193-
194192
if (!Z_PTR(thisfilter->abstract)) {
195193
return FAILURE;
196194
}
197195

198-
data = (php_bz2_filter_data *)Z_PTR(thisfilter->abstract);
196+
php_bz2_filter_data *data = Z_PTR(thisfilter->abstract);
199197

200198
/* End current decompression if running */
201199
if (data->status == PHP_BZ2_RUNNING) {
@@ -332,14 +330,13 @@ static zend_result php_bz2_compress_seek(
332330
int whence
333331
)
334332
{
335-
php_bz2_filter_data *data;
336333
int status;
337334

338335
if (!Z_PTR(thisfilter->abstract)) {
339336
return FAILURE;
340337
}
341338

342-
data = (php_bz2_filter_data *)Z_PTR(thisfilter->abstract);
339+
php_bz2_filter_data *data = Z_PTR(thisfilter->abstract);
343340

344341
/* End current compression */
345342
BZ2_bzCompressEnd(&(data->strm));
@@ -481,7 +478,7 @@ static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *fi
481478
return NULL;
482479
}
483480

484-
return php_stream_filter_alloc(fops, data, persistent, PHP_STREAM_FILTER_SEEKABLE_START);
481+
return php_stream_filter_alloc(fops, data, persistent, PSFS_SEEKABLE_START);
485482
}
486483

487484
const php_stream_filter_factory php_bz2_filter_factory = {

ext/iconv/iconv.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2286,6 +2286,7 @@ PHP_FUNCTION(iconv_get_encoding)
22862286

22872287
}
22882288
/* }}} */
2289+
22892290
/* {{{ iconv stream filter */
22902291
typedef struct _php_iconv_stream_filter {
22912292
iconv_t cd;
@@ -2568,7 +2569,8 @@ static zend_result php_iconv_stream_filter_seek(
25682569
/* Reset iconv conversion state by closing and reopening the converter */
25692570
iconv_close(self->cd);
25702571

2571-
if ((iconv_t)-1 == (self->cd = iconv_open(self->to_charset, self->from_charset))) {
2572+
self->cd = iconv_open(self->to_charset, self->from_charset);
2573+
if ((iconv_t)-1 == self->cd) {
25722574
php_error_docref(NULL, E_WARNING,
25732575
"iconv stream filter (\"%s\"=>\"%s\"): failed to reset conversion state",
25742576
self->from_charset, self->to_charset);
@@ -2628,7 +2630,7 @@ static php_stream_filter *php_iconv_stream_filter_factory_create(const char *nam
26282630
}
26292631

26302632
return php_stream_filter_alloc(&php_iconv_stream_filter_ops, inst, persistent,
2631-
PHP_STREAM_FILTER_SEEKABLE_START);
2633+
PSFS_SEEKABLE_START);
26322634
}
26332635
/* }}} */
26342636

ext/standard/filters.c

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,7 @@ static const php_stream_filter_ops strfilter_rot13_ops = {
6565

6666
static php_stream_filter *strfilter_rot13_create(const char *filtername, zval *filterparams, bool persistent)
6767
{
68-
return php_stream_filter_alloc(&strfilter_rot13_ops, NULL, persistent,
69-
PHP_STREAM_FILTER_SEEKABLE_ALWAYS);
68+
return php_stream_filter_alloc(&strfilter_rot13_ops, NULL, persistent, PSFS_SEEKABLE_ALWAYS);
7069
}
7170

7271
static const php_stream_filter_factory strfilter_rot13_factory = {
@@ -150,14 +149,12 @@ static const php_stream_filter_ops strfilter_tolower_ops = {
150149

151150
static php_stream_filter *strfilter_toupper_create(const char *filtername, zval *filterparams, bool persistent)
152151
{
153-
return php_stream_filter_alloc(&strfilter_toupper_ops, NULL, persistent,
154-
PHP_STREAM_FILTER_SEEKABLE_ALWAYS);
152+
return php_stream_filter_alloc(&strfilter_toupper_ops, NULL, persistent, PSFS_SEEKABLE_ALWAYS);
155153
}
156154

157155
static php_stream_filter *strfilter_tolower_create(const char *filtername, zval *filterparams, bool persistent)
158156
{
159-
return php_stream_filter_alloc(&strfilter_tolower_ops, NULL, persistent,
160-
PHP_STREAM_FILTER_SEEKABLE_ALWAYS);
157+
return php_stream_filter_alloc(&strfilter_tolower_ops, NULL, persistent, PSFS_SEEKABLE_ALWAYS);
161158
}
162159

163160
static const php_stream_filter_factory strfilter_toupper_factory = {
@@ -1672,8 +1669,7 @@ static php_stream_filter *strfilter_convert_create(const char *filtername, zval
16721669
return NULL;
16731670
}
16741671

1675-
return php_stream_filter_alloc(&strfilter_convert_ops, inst, persistent,
1676-
PHP_STREAM_FILTER_SEEKABLE_START);
1672+
return php_stream_filter_alloc(&strfilter_convert_ops, inst, persistent, PSFS_SEEKABLE_START);
16771673
}
16781674

16791675
static const php_stream_filter_factory strfilter_convert_factory = {
@@ -1767,8 +1763,7 @@ static php_stream_filter *consumed_filter_create(const char *filtername, zval *f
17671763
data->offset = ~0;
17681764
fops = &consumed_filter_ops;
17691765

1770-
return php_stream_filter_alloc(fops, data, persistent,
1771-
PHP_STREAM_FILTER_SEEKABLE_START);
1766+
return php_stream_filter_alloc(fops, data, persistent, PSFS_SEEKABLE_START);
17721767
}
17731768

17741769
static const php_stream_filter_factory consumed_filter_factory = {
@@ -1999,8 +1994,7 @@ static php_stream_filter *chunked_filter_create(const char *filtername, zval *fi
19991994
data->persistent = persistent;
20001995
fops = &chunked_filter_ops;
20011996

2002-
return php_stream_filter_alloc(fops, data, persistent,
2003-
PHP_STREAM_FILTER_SEEKABLE_START);
1997+
return php_stream_filter_alloc(fops, data, persistent, PSFS_SEEKABLE_START);
20041998
}
20051999

20062000
static const php_stream_filter_factory chunked_filter_factory = {

ext/standard/user_filters.c

Lines changed: 47 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,33 @@ static void userfilter_dtor(php_stream_filter *thisfilter)
133133
zval_ptr_dtor(obj);
134134
}
135135

136+
static zend_result userfilter_assign_stream(php_stream *stream, zval *obj, zend_string **stream_name_p)
137+
{
138+
/* Give the userfilter class a hook back to the stream */
139+
const zend_class_entry *old_scope = EG(fake_scope);
140+
EG(fake_scope) = Z_OBJCE_P(obj);
141+
142+
zend_string *stream_name = ZSTR_INIT_LITERAL("stream", 0);
143+
bool stream_property_exists = Z_OBJ_HT_P(obj)->has_property(Z_OBJ_P(obj), stream_name, ZEND_PROPERTY_EXISTS, NULL);
144+
if (stream_property_exists) {
145+
zval stream_zval;
146+
php_stream_to_zval(stream, &stream_zval);
147+
zend_update_property_ex(Z_OBJCE_P(obj), Z_OBJ_P(obj), stream_name, &stream_zval);
148+
/* If property update threw an exception, skip filter execution */
149+
if (EG(exception)) {
150+
EG(fake_scope) = old_scope;
151+
zend_string_release(stream_name);
152+
return FAILURE;
153+
}
154+
*stream_name_p = stream_name;
155+
} else {
156+
zend_string_release(stream_name);
157+
}
158+
EG(fake_scope) = old_scope;
159+
160+
return SUCCESS;
161+
}
162+
136163
static php_stream_filter_status_t userfilter_filter(
137164
php_stream *stream,
138165
php_stream_filter *thisfilter,
@@ -158,31 +185,16 @@ static php_stream_filter_status_t userfilter_filter(
158185
uint32_t orig_no_fclose = stream->flags & PHP_STREAM_FLAG_NO_FCLOSE;
159186
stream->flags |= PHP_STREAM_FLAG_NO_FCLOSE;
160187

161-
/* Give the userfilter class a hook back to the stream */
162-
const zend_class_entry *old_scope = EG(fake_scope);
163-
EG(fake_scope) = Z_OBJCE_P(obj);
164-
165-
zend_string *stream_name = ZSTR_INIT_LITERAL("stream", 0);
166-
bool stream_property_exists = Z_OBJ_HT_P(obj)->has_property(Z_OBJ_P(obj), stream_name, ZEND_PROPERTY_EXISTS, NULL);
167-
if (stream_property_exists) {
168-
zval stream_zval;
169-
php_stream_to_zval(stream, &stream_zval);
170-
zend_update_property_ex(Z_OBJCE_P(obj), Z_OBJ_P(obj), stream_name, &stream_zval);
171-
/* If property update threw an exception, skip filter execution */
172-
if (EG(exception)) {
173-
EG(fake_scope) = old_scope;
174-
if (buckets_in->head) {
175-
php_error_docref(NULL, E_WARNING, "Unprocessed filter buckets remaining on input brigade");
176-
}
177-
zend_string_release(stream_name);
178-
stream->flags &= ~PHP_STREAM_FLAG_NO_FCLOSE;
179-
stream->flags |= orig_no_fclose;
180-
return PSFS_ERR_FATAL;
188+
zend_string *stream_name = NULL;
189+
if (userfilter_assign_stream(stream, obj, &stream_name) == FAILURE) {
190+
if (buckets_in->head) {
191+
php_error_docref(NULL, E_WARNING, "Unprocessed filter buckets remaining on input brigade");
181192
}
193+
stream->flags &= ~PHP_STREAM_FLAG_NO_FCLOSE;
194+
stream->flags |= orig_no_fclose;
195+
return PSFS_ERR_FATAL;
182196
}
183197

184-
EG(fake_scope) = old_scope;
185-
186198
ZVAL_STRINGL(&func_name, "filter", sizeof("filter")-1);
187199

188200
/* Setup calling arguments */
@@ -227,12 +239,11 @@ static php_stream_filter_status_t userfilter_filter(
227239
* Since the property accepted a resource assignment above, it must have
228240
* no type hint or be typed as mixed, so we can safely assign null.
229241
*/
230-
if (stream_property_exists) {
242+
if (stream_name != NULL) {
231243
zend_update_property_null(Z_OBJCE_P(obj), Z_OBJ_P(obj), ZSTR_VAL(stream_name), ZSTR_LEN(stream_name));
244+
zend_string_release(stream_name);
232245
}
233246

234-
zend_string_release(stream_name);
235-
236247
zval_ptr_dtor(&args[3]);
237248
zval_ptr_dtor(&args[2]);
238249
zval_ptr_dtor(&args[1]);
@@ -269,21 +280,20 @@ static zend_result userfilter_seek(
269280
/* Method doesn't exist - consider this a successful seek for BC */
270281
return SUCCESS;
271282
}
272-
zend_string_release(method_name);
273283

274284
/* Make sure the stream is not closed while the filter callback executes. */
275285
uint32_t orig_no_fclose = stream->flags & PHP_STREAM_FLAG_NO_FCLOSE;
276286
stream->flags |= PHP_STREAM_FLAG_NO_FCLOSE;
277287

278-
zval *stream_prop = zend_hash_str_find_ind(Z_OBJPROP_P(obj), "stream", sizeof("stream")-1);
279-
if (stream_prop) {
280-
/* Give the userfilter class a hook back to the stream */
281-
zval_ptr_dtor(stream_prop);
282-
php_stream_to_zval(stream, stream_prop);
283-
Z_ADDREF_P(stream_prop);
288+
zend_string *stream_name = NULL;
289+
if (userfilter_assign_stream(stream, obj, &stream_name) == FAILURE) {
290+
stream->flags &= ~PHP_STREAM_FLAG_NO_FCLOSE;
291+
stream->flags |= orig_no_fclose;
292+
zend_string_release(method_name);
293+
return FAILURE;
284294
}
285295

286-
ZVAL_STRINGL(&func_name, "seek", sizeof("seek")-1);
296+
ZVAL_STR(&func_name, method_name);
287297

288298
/* Setup calling arguments */
289299
ZVAL_LONG(&args[0], offset);
@@ -308,13 +318,11 @@ static zend_result userfilter_seek(
308318
/* filter resources are cleaned up by the stream destructor,
309319
* keeping a reference to the stream resource here would prevent it
310320
* from being destroyed properly */
311-
if (stream_prop) {
312-
convert_to_null(stream_prop);
321+
if (stream_name != NULL) {
322+
zend_update_property_null(Z_OBJCE_P(obj), Z_OBJ_P(obj), ZSTR_VAL(stream_name), ZSTR_LEN(stream_name));
323+
zend_string_release(stream_name);
313324
}
314325

315-
zval_ptr_dtor(&args[1]);
316-
zval_ptr_dtor(&args[0]);
317-
318326
stream->flags &= ~PHP_STREAM_FLAG_NO_FCLOSE;
319327
stream->flags |= orig_no_fclose;
320328

@@ -392,8 +400,7 @@ static php_stream_filter *user_filter_factory_create(const char *filtername,
392400
return NULL;
393401
}
394402

395-
filter = php_stream_filter_alloc(&userfilter_ops, NULL, false,
396-
PHP_STREAM_FILTER_SEEKABLE_CHECK);
403+
filter = php_stream_filter_alloc(&userfilter_ops, NULL, false, PSFS_SEEKABLE_CHECK);
397404

398405
/* filtername */
399406
add_property_string(&obj, "filtername", filtername);

ext/zlib/zlib_filter.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,14 +151,13 @@ static zend_result php_zlib_inflate_seek(
151151
int whence
152152
)
153153
{
154-
php_zlib_filter_data *data;
155154
int status;
156155

157156
if (!thisfilter || !Z_PTR(thisfilter->abstract)) {
158157
return FAILURE;
159158
}
160159

161-
data = (php_zlib_filter_data *)(Z_PTR(thisfilter->abstract));
160+
php_zlib_filter_data *data = Z_PTR(thisfilter->abstract);
162161

163162
if (data->finished) {
164163
/* Stream was ended, need to reinitialize */
@@ -310,14 +309,13 @@ static zend_result php_zlib_deflate_seek(
310309
int whence
311310
)
312311
{
313-
php_zlib_filter_data *data;
314312
int status;
315313

316314
if (!thisfilter || !Z_PTR(thisfilter->abstract)) {
317315
return FAILURE;
318316
}
319317

320-
data = (php_zlib_filter_data *)(Z_PTR(thisfilter->abstract));
318+
php_zlib_filter_data *data = Z_PTR(thisfilter->abstract);
321319

322320
/* Reset zlib deflation state */
323321
status = deflateReset(&(data->strm));
@@ -502,7 +500,7 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f
502500
return NULL;
503501
}
504502

505-
return php_stream_filter_alloc(fops, data, persistent, PHP_STREAM_FILTER_SEEKABLE_START);
503+
return php_stream_filter_alloc(fops, data, persistent, PSFS_SEEKABLE_START);
506504
}
507505

508506
const php_stream_filter_factory php_zlib_filter_factory = {

main/streams/filter.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,15 +261,15 @@ PHPAPI php_stream_filter *php_stream_filter_create(const char *filtername, zval
261261
}
262262

263263
PHPAPI php_stream_filter *_php_stream_filter_alloc(const php_stream_filter_ops *fops,
264-
void *abstract, bool persistent, uint32_t flags STREAMS_DC)
264+
void *abstract, bool persistent, php_stream_filter_seekable_t seekable STREAMS_DC)
265265
{
266266
php_stream_filter *filter;
267267

268268
filter = (php_stream_filter*) pemalloc_rel_orig(sizeof(php_stream_filter), persistent);
269269
memset(filter, 0, sizeof(php_stream_filter));
270270

271271
filter->fops = fops;
272-
filter->seekable = flags & PHP_STREAM_FILTER_SEEKABLE_MASK;
272+
filter->seekable = seekable;
273273
Z_PTR(filter->abstract) = abstract;
274274
filter->is_persistent = persistent;
275275

main/streams/php_stream_filter_api.h

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,6 @@
3434
#define PHP_STREAM_FILTER_WRITE 0x0002
3535
#define PHP_STREAM_FILTER_ALL (PHP_STREAM_FILTER_READ | PHP_STREAM_FILTER_WRITE)
3636

37-
#define PHP_STREAM_FILTER_SEEKABLE_NEVER 0
38-
#define PHP_STREAM_FILTER_SEEKABLE_START 1
39-
#define PHP_STREAM_FILTER_SEEKABLE_CHECK 2
40-
#define PHP_STREAM_FILTER_SEEKABLE_ALWAYS 3
41-
#define PHP_STREAM_FILTER_SEEKABLE_MASK 3
42-
4337
typedef struct _php_stream_bucket php_stream_bucket;
4438
typedef struct _php_stream_bucket_brigade php_stream_bucket_brigade;
4539

@@ -67,6 +61,13 @@ typedef enum {
6761
PSFS_PASS_ON /* filter generated output buckets; pass them on to next in chain */
6862
} php_stream_filter_status_t;
6963

64+
typedef enum {
65+
PSFS_SEEKABLE_NEVER, /* seeking filter never possible */
66+
PSFS_SEEKABLE_START, /* seeking possible only to start (position 0) */
67+
PSFS_SEEKABLE_CHECK, /* seeking possible but it is always checked if callback function set */
68+
PSFS_SEEKABLE_ALWAYS, /* seeking is always possible */
69+
} php_stream_filter_seekable_t;
70+
7071
/* Buckets API. */
7172
BEGIN_EXTERN_C()
7273
PHPAPI php_stream_bucket *php_stream_bucket_new(const php_stream *stream, char *buf, size_t buflen, uint8_t own_buf, uint8_t buf_persistent);
@@ -119,8 +120,8 @@ struct _php_stream_filter {
119120
zval abstract; /* for use by filter implementation */
120121
php_stream_filter *next;
121122
php_stream_filter *prev;
123+
php_stream_filter_seekable_t seekable;
122124
bool is_persistent;
123-
uint8_t seekable;
124125

125126
/* link into stream and chain */
126127
php_stream_filter_chain *chain;
@@ -142,13 +143,13 @@ PHPAPI zend_result _php_stream_filter_flush(php_stream_filter *filter, bool fini
142143
PHPAPI php_stream_filter *php_stream_filter_remove(php_stream_filter *filter, bool call_dtor);
143144
PHPAPI void php_stream_filter_free(php_stream_filter *filter);
144145
PHPAPI php_stream_filter *_php_stream_filter_alloc(const php_stream_filter_ops *fops,
145-
void *abstract, bool persistent, uint32_t flags STREAMS_DC);
146+
void *abstract, bool persistent, php_stream_filter_seekable_t seekable STREAMS_DC);
146147

147148
END_EXTERN_C()
148-
#define php_stream_filter_alloc(fops, thisptr, persistent, flags) \
149-
_php_stream_filter_alloc((fops), (thisptr), (persistent), (flags) STREAMS_CC)
150-
#define php_stream_filter_alloc_rel(fops, thisptr, persistent, flags) \
151-
_php_stream_filter_alloc((fops), (thisptr), (persistent), (flags) STREAMS_REL_CC)
149+
#define php_stream_filter_alloc(fops, thisptr, persistent, seekable) \
150+
_php_stream_filter_alloc((fops), (thisptr), (persistent), (seekable) STREAMS_CC)
151+
#define php_stream_filter_alloc_rel(fops, thisptr, persistent, seekable) \
152+
_php_stream_filter_alloc((fops), (thisptr), (persistent), (seekable) STREAMS_REL_CC)
152153
#define php_stream_filter_prepend(chain, filter) _php_stream_filter_prepend((chain), (filter))
153154
#define php_stream_filter_append(chain, filter) _php_stream_filter_append((chain), (filter))
154155
#define php_stream_filter_flush(filter, finish) _php_stream_filter_flush((filter), (finish))

0 commit comments

Comments
 (0)