pollita Wed Mar 31 18:48:59 2004 EDT
Added files:
/php-src/ext/standard/tests/file bug27619.phpt
Modified files:
/php-src/main/streams php_stream_filter_api.h filter.c streams.c
/php-src NEWS
Log:
BugFix#27619
Filters not applied to pre-buffered stream data.
(esp. http:// streams)
http://cvs.php.net/diff.php/php-src/main/streams/php_stream_filter_api.h?r1=1.7&r2=1.8&ty=u
Index: php-src/main/streams/php_stream_filter_api.h
diff -u php-src/main/streams/php_stream_filter_api.h:1.7
php-src/main/streams/php_stream_filter_api.h:1.8
--- php-src/main/streams/php_stream_filter_api.h:1.7 Fri Feb 20 03:22:12 2004
+++ php-src/main/streams/php_stream_filter_api.h Wed Mar 31 18:48:59 2004
@@ -19,7 +19,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: php_stream_filter_api.h,v 1.7 2004/02/20 08:22:12 hholzgra Exp $ */
+/* $Id: php_stream_filter_api.h,v 1.8 2004/03/31 23:48:59 pollita Exp $ */
/* The filter API works on the principle of "Bucket-Brigades". This is
* partially inspired by the Apache 2 method of doing things, although
@@ -100,6 +100,9 @@
typedef struct _php_stream_filter_chain {
php_stream_filter *head, *tail;
+
+ /* Owning stream */
+ php_stream *stream;
} php_stream_filter_chain;
struct _php_stream_filter {
@@ -118,14 +121,16 @@
/* stack filter onto a stream */
BEGIN_EXTERN_C()
-PHPAPI void php_stream_filter_prepend(php_stream_filter_chain *chain,
php_stream_filter *filter);
-PHPAPI void php_stream_filter_append(php_stream_filter_chain *chain,
php_stream_filter *filter);
+PHPAPI void _php_stream_filter_prepend(php_stream_filter_chain *chain,
php_stream_filter *filter TSRMLS_DC);
+PHPAPI void _php_stream_filter_append(php_stream_filter_chain *chain,
php_stream_filter *filter TSRMLS_DC);
PHPAPI php_stream_filter *php_stream_filter_remove(php_stream_filter *filter, int
call_dtor TSRMLS_DC);
PHPAPI void php_stream_filter_free(php_stream_filter *filter TSRMLS_DC);
PHPAPI php_stream_filter *_php_stream_filter_alloc(php_stream_filter_ops *fops, void
*abstract, int persistent STREAMS_DC TSRMLS_DC);
END_EXTERN_C()
#define php_stream_filter_alloc(fops, thisptr, persistent)
_php_stream_filter_alloc((fops), (thisptr), (persistent) STREAMS_CC TSRMLS_CC)
#define php_stream_filter_alloc_rel(fops, thisptr, persistent)
_php_stream_filter_alloc((fops), (thisptr), (persistent) STREAMS_REL_CC TSRMLS_CC)
+#define php_stream_fitler_prepend(chain, filter) _php_stream_filter_prepend((chain),
(filter) TSRMLS_CC)
+#define php_stream_fitler_append(chain, filter) _php_stream_filter_append((chain),
(filter) TSRMLS_CC)
#define php_stream_is_filtered(stream) ((stream)->readfilters.head ||
(stream)->writefilters.head)
http://cvs.php.net/diff.php/php-src/main/streams/filter.c?r1=1.9&r2=1.10&ty=u
Index: php-src/main/streams/filter.c
diff -u php-src/main/streams/filter.c:1.9 php-src/main/streams/filter.c:1.10
--- php-src/main/streams/filter.c:1.9 Thu Jan 8 03:17:59 2004
+++ php-src/main/streams/filter.c Wed Mar 31 18:48:59 2004
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: filter.c,v 1.9 2004/01/08 08:17:59 andi Exp $ */
+/* $Id: filter.c,v 1.10 2004/03/31 23:48:59 pollita Exp $ */
#include "php.h"
#include "php_globals.h"
@@ -283,7 +283,7 @@
pefree(filter, filter->is_persistent);
}
-PHPAPI void php_stream_filter_prepend(php_stream_filter_chain *chain,
php_stream_filter *filter)
+PHPAPI void php_stream_filter_prepend(php_stream_filter_chain *chain,
php_stream_filter *filter TSRMLS_DC)
{
filter->next = chain->head;
filter->prev = NULL;
@@ -297,8 +297,10 @@
filter->chain = chain;
}
-PHPAPI void php_stream_filter_append(php_stream_filter_chain *chain,
php_stream_filter *filter)
+PHPAPI void php_stream_filter_append(php_stream_filter_chain *chain,
php_stream_filter *filter TSRMLS_DC)
{
+ php_stream *stream = chain->stream;
+
filter->prev = chain->tail;
filter->next = NULL;
if (chain->tail) {
@@ -308,6 +310,75 @@
}
chain->tail = filter;
filter->chain = chain;
+
+ if ((stream->writepos - stream->readpos) > 0) {
+ /* Let's going ahead and wind anything in the buffer through this
filter */
+ php_stream_bucket_brigade brig_in = { NULL, NULL }, brig_out = { NULL,
NULL };
+ php_stream_bucket_brigade *brig_inp = &brig_in, *brig_outp = &brig_out;
+ php_stream_filter_status_t status;
+ php_stream_bucket *bucket;
+ size_t consumed = 0;
+
+ bucket = php_stream_bucket_new(stream, stream->readbuf +
stream->readpos, stream->writepos - stream->readpos, 0, 0 TSRMLS_CC);
+ php_stream_bucket_append(brig_inp, bucket TSRMLS_CC);
+ status = filter->fops->filter(stream, filter, brig_inp, brig_outp,
&consumed, PSFS_FLAG_NORMAL TSRMLS_CC);
+
+ if (stream->readpos + consumed > stream->writepos || consumed < 0) {
+ /* No behaving filter should cause this. */
+ status = PSFS_ERR_FATAL;
+ }
+
+ switch (status) {
+ case PSFS_ERR_FATAL:
+ /* If this first cycle simply fails then there's
something wrong with the filter.
+ Pull the filter off the chain and leave the read
buffer alone. */
+ if (chain->head == filter) {
+ chain->head = NULL;
+ chain->tail = NULL;
+ } else {
+ filter->prev->next = NULL;
+ chain->tail = filter->prev;
+ }
+ php_stream_bucket_unlink(bucket TSRMLS_CC);
+ php_stream_bucket_delref(bucket TSRMLS_CC);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Filter
failed to process pre-buffered data. Not adding to filterchain.");
+ break;
+ case PSFS_FEED_ME:
+ /* We don't actually need data yet,
+ leave this filter in a feed me state until data is
needed.
+ Reset stream's internal read buffer since the
filter is "holding" it. */
+ stream->readpos = 0;
+ stream->writepos = 0;
+ break;
+ case PSFS_PASS_ON:
+ /* Put any filtered data onto the readbuffer stack.
+ Previously read data has been at least partially
consumed. */
+ stream->readpos += consumed;
+
+ if (stream->writepos == stream->readpos) {
+ /* Entirely consumed */
+ stream->writepos = 0;
+ stream->readpos = 0;
+ }
+
+ while (brig_outp->head) {
+ bucket = brig_outp->head;
+ /* Grow buffer to hold this bucket if need be.
+ TODO: See warning in
main/stream/streams.c::php_stream_fill_read_buffer */
+ if (stream->readbuflen - stream->writepos <
bucket->buflen) {
+ stream->readbuflen += bucket->buflen;
+ stream->readbuf =
perealloc(stream->readbuf, stream->readbuflen, stream->is_persistent);
+ }
+ memcpy(stream->readbuf + stream->writepos,
bucket->buf, bucket->buflen);
+ stream->writepos += bucket->buflen;
+
+ php_stream_bucket_unlink(bucket TSRMLS_CC);
+ php_stream_bucket_delref(bucket TSRMLS_CC);
+ }
+ break;
+ }
+ }
+
}
PHPAPI php_stream_filter *php_stream_filter_remove(php_stream_filter *filter, int
call_dtor TSRMLS_DC)
http://cvs.php.net/diff.php/php-src/main/streams/streams.c?r1=1.52&r2=1.53&ty=u
Index: php-src/main/streams/streams.c
diff -u php-src/main/streams/streams.c:1.52 php-src/main/streams/streams.c:1.53
--- php-src/main/streams/streams.c:1.52 Sun Mar 7 17:06:36 2004
+++ php-src/main/streams/streams.c Wed Mar 31 18:48:59 2004
@@ -19,7 +19,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: streams.c,v 1.52 2004/03/07 22:06:36 wez Exp $ */
+/* $Id: streams.c,v 1.53 2004/03/31 23:48:59 pollita Exp $ */
#define _GNU_SOURCE
#include "php.h"
@@ -216,6 +216,9 @@
memset(ret, 0, sizeof(php_stream));
+ ret->readfilters.stream = ret;
+ ret->writefilters.stream = ret;
+
#if STREAM_DEBUG
fprintf(stderr, "stream_alloc: %s:%p persistent=%s\n", ops->label, ret,
persistent_id);
#endif
http://cvs.php.net/diff.php/php-src/NEWS?r1=1.1663&r2=1.1664&ty=u
Index: php-src/NEWS
diff -u php-src/NEWS:1.1663 php-src/NEWS:1.1664
--- php-src/NEWS:1.1663 Sun Mar 28 10:03:56 2004
+++ php-src/NEWS Wed Mar 31 18:48:59 2004
@@ -15,6 +15,7 @@
(Dmitry, Andi)
- Fixed bug #27628 (Simplify the process of making a POST request via stream
context). (Ilia)
+- Fixed bug #27619 (filters not applied to pre-buffered stream data). (Sara)
- Fixed bug #27469 (serialize() objects of incomplete class). (Dmitry)
- Fixed bug #27457 (handling of numeric indexes in strtr()). (Dmitry)
http://cvs.php.net/co.php/php-src/ext/standard/tests/file/bug27619.phpt?r=1.1&p=1
Index: php-src/ext/standard/tests/file/bug27619.phpt
+++ php-src/ext/standard/tests/file/bug27619.phpt
--TEST--
Bug #27619 (filters not applied to pre-buffered data)
--FILE--
<?php
$fp = tmpfile();
fwrite($fp, "this is a lowercase string.\n");
rewind($fp);
/* Echo out the first four bytes 'this' without applying filter
Remainder will get sucked into the read buffer though. */
echo fread($fp, 4);
stream_filter_append($fp, "string.toupper");
fpassthru($fp);
?>
--EXPECT--
this IS A LOWERCASE STRING.
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php