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