1 /* 2 +----------------------------------------------------------------------+ 3 | Copyright (c) The PHP Group | 4 +----------------------------------------------------------------------+ 5 | This source file is subject to version 3.01 of the PHP license, | 6 | that is bundled with this package in the file LICENSE, and is | 7 | available through the world-wide-web at the following url: | 8 | https://www.php.net/license/3_01.txt | 9 | If you did not receive a copy of the PHP license and are unable to | 10 | obtain it through the world-wide-web, please send a note to | 11 | license@php.net so we can mail you a copy immediately. | 12 +----------------------------------------------------------------------+ 13 | Author: Wez Furlong <wez@thebrainroom.com> | 14 | With suggestions from: | 15 | Moriyoshi Koizumi <moriyoshi@at.wakwak.com> | 16 | Sara Golemon <pollita@php.net> | 17 +----------------------------------------------------------------------+ 18 */ 19 20 /* The filter API works on the principle of "Bucket-Brigades". This is 21 * partially inspired by the Apache 2 method of doing things, although 22 * it is intentionally a light-weight implementation. 23 * 24 * Each stream can have a chain of filters for reading and another for writing. 25 * 26 * When data is written to the stream, it is placed into a bucket and placed at 27 * the start of the input brigade. 28 * 29 * The first filter in the chain is invoked on the brigade and (depending on 30 * it's return value), the next filter is invoked and so on. 31 * */ 32 33 #define PHP_STREAM_FILTER_READ 0x0001 34 #define PHP_STREAM_FILTER_WRITE 0x0002 35 #define PHP_STREAM_FILTER_ALL (PHP_STREAM_FILTER_READ | PHP_STREAM_FILTER_WRITE) 36 37 typedef struct _php_stream_bucket php_stream_bucket; 38 typedef struct _php_stream_bucket_brigade php_stream_bucket_brigade; 39 40 struct _php_stream_bucket { 41 php_stream_bucket *next, *prev; 42 php_stream_bucket_brigade *brigade; 43 44 char *buf; 45 size_t buflen; 46 /* if non-zero, buf should be pefreed when the bucket is destroyed */ 47 uint8_t own_buf; 48 uint8_t is_persistent; 49 50 /* destroy this struct when refcount falls to zero */ 51 int refcount; 52 }; 53 54 struct _php_stream_bucket_brigade { 55 php_stream_bucket *head, *tail; 56 }; 57 58 typedef enum { 59 PSFS_ERR_FATAL, /* error in data stream */ 60 PSFS_FEED_ME, /* filter needs more data; stop processing chain until more is available */ 61 PSFS_PASS_ON /* filter generated output buckets; pass them on to next in chain */ 62 } php_stream_filter_status_t; 63 64 /* Buckets API. */ 65 BEGIN_EXTERN_C() 66 PHPAPI php_stream_bucket *php_stream_bucket_new(php_stream *stream, char *buf, size_t buflen, uint8_t own_buf, uint8_t buf_persistent); 67 PHPAPI int php_stream_bucket_split(php_stream_bucket *in, php_stream_bucket **left, php_stream_bucket **right, size_t length); 68 PHPAPI void php_stream_bucket_delref(php_stream_bucket *bucket); 69 #define php_stream_bucket_addref(bucket) (bucket)->refcount++ 70 PHPAPI void php_stream_bucket_prepend(php_stream_bucket_brigade *brigade, php_stream_bucket *bucket); 71 PHPAPI void php_stream_bucket_append(php_stream_bucket_brigade *brigade, php_stream_bucket *bucket); 72 PHPAPI void php_stream_bucket_unlink(php_stream_bucket *bucket); 73 PHPAPI php_stream_bucket *php_stream_bucket_make_writeable(php_stream_bucket *bucket); 74 END_EXTERN_C() 75 76 #define PSFS_FLAG_NORMAL 0 /* regular read/write */ 77 #define PSFS_FLAG_FLUSH_INC 1 /* an incremental flush */ 78 #define PSFS_FLAG_FLUSH_CLOSE 2 /* final flush prior to closing */ 79 80 typedef struct _php_stream_filter_ops { 81 82 php_stream_filter_status_t (*filter)( 83 php_stream *stream, 84 php_stream_filter *thisfilter, 85 php_stream_bucket_brigade *buckets_in, 86 php_stream_bucket_brigade *buckets_out, 87 size_t *bytes_consumed, 88 int flags 89 ); 90 91 void (*dtor)(php_stream_filter *thisfilter); 92 93 const char *label; 94 95 } php_stream_filter_ops; 96 97 typedef struct _php_stream_filter_chain { 98 php_stream_filter *head, *tail; 99 100 /* Owning stream */ 101 php_stream *stream; 102 } php_stream_filter_chain; 103 104 struct _php_stream_filter { 105 const php_stream_filter_ops *fops; 106 zval abstract; /* for use by filter implementation */ 107 php_stream_filter *next; 108 php_stream_filter *prev; 109 int is_persistent; 110 111 /* link into stream and chain */ 112 php_stream_filter_chain *chain; 113 114 /* buffered buckets */ 115 php_stream_bucket_brigade buffer; 116 117 /* filters are auto_registered when they're applied */ 118 zend_resource *res; 119 }; 120 121 /* stack filter onto a stream */ 122 BEGIN_EXTERN_C() 123 PHPAPI void _php_stream_filter_prepend(php_stream_filter_chain *chain, php_stream_filter *filter); 124 PHPAPI int php_stream_filter_prepend_ex(php_stream_filter_chain *chain, php_stream_filter *filter); 125 PHPAPI void _php_stream_filter_append(php_stream_filter_chain *chain, php_stream_filter *filter); 126 PHPAPI int php_stream_filter_append_ex(php_stream_filter_chain *chain, php_stream_filter *filter); 127 PHPAPI int _php_stream_filter_flush(php_stream_filter *filter, int finish); 128 PHPAPI php_stream_filter *php_stream_filter_remove(php_stream_filter *filter, int call_dtor); 129 PHPAPI void php_stream_filter_free(php_stream_filter *filter); 130 PHPAPI php_stream_filter *_php_stream_filter_alloc(const php_stream_filter_ops *fops, void *abstract, uint8_t persistent STREAMS_DC); 131 END_EXTERN_C() 132 #define php_stream_filter_alloc(fops, thisptr, persistent) _php_stream_filter_alloc((fops), (thisptr), (persistent) STREAMS_CC) 133 #define php_stream_filter_alloc_rel(fops, thisptr, persistent) _php_stream_filter_alloc((fops), (thisptr), (persistent) STREAMS_REL_CC) 134 #define php_stream_filter_prepend(chain, filter) _php_stream_filter_prepend((chain), (filter)) 135 #define php_stream_filter_append(chain, filter) _php_stream_filter_append((chain), (filter)) 136 #define php_stream_filter_flush(filter, finish) _php_stream_filter_flush((filter), (finish)) 137 138 #define php_stream_is_filtered(stream) ((stream)->readfilters.head || (stream)->writefilters.head) 139 140 typedef struct _php_stream_filter_factory { 141 php_stream_filter *(*create_filter)(const char *filtername, zval *filterparams, uint8_t persistent); 142 } php_stream_filter_factory; 143 144 BEGIN_EXTERN_C() 145 PHPAPI int php_stream_filter_register_factory(const char *filterpattern, const php_stream_filter_factory *factory); 146 PHPAPI int php_stream_filter_unregister_factory(const char *filterpattern); 147 PHPAPI int php_stream_filter_register_factory_volatile(zend_string *filterpattern, const php_stream_filter_factory *factory); 148 PHPAPI php_stream_filter *php_stream_filter_create(const char *filtername, zval *filterparams, uint8_t persistent); 149 END_EXTERN_C() 150