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

Reply via email to