Lines 90-100
apr_status_t ap_core_input_filter(ap_filter_t *f,
Link Here
|
90 |
ap_input_mode_t mode, apr_read_type_e block, |
90 |
ap_input_mode_t mode, apr_read_type_e block, |
91 |
apr_off_t readbytes) |
91 |
apr_off_t readbytes) |
92 |
{ |
92 |
{ |
93 |
apr_status_t rv; |
93 |
apr_status_t rv = APR_SUCCESS; |
94 |
core_net_rec *net = f->ctx; |
94 |
core_net_rec *net = f->ctx; |
95 |
core_ctx_t *ctx = net->in_ctx; |
95 |
core_ctx_t *ctx = net->in_ctx; |
96 |
const char *str; |
96 |
const char *str; |
97 |
apr_size_t len; |
97 |
apr_size_t len; |
|
|
98 |
apr_bucket *e; |
98 |
|
99 |
|
99 |
if (mode == AP_MODE_INIT) { |
100 |
if (mode == AP_MODE_INIT) { |
100 |
/* |
101 |
/* |
Lines 110-115
apr_status_t ap_core_input_filter(ap_filter_t *f,
Link Here
|
110 |
return APR_SUCCESS; |
111 |
return APR_SUCCESS; |
111 |
} |
112 |
} |
112 |
|
113 |
|
|
|
114 |
f->c->data_in_input_filters &= ~1; /* until further notice */ |
115 |
|
113 |
if (!ctx) |
116 |
if (!ctx) |
114 |
{ |
117 |
{ |
115 |
net->in_ctx = ctx = apr_palloc(f->c->pool, sizeof(*ctx)); |
118 |
net->in_ctx = ctx = apr_palloc(f->c->pool, sizeof(*ctx)); |
Lines 147-153
apr_status_t ap_core_input_filter(ap_filter_t *f,
Link Here
|
147 |
if (APR_STATUS_IS_EAGAIN(rv) && block == APR_NONBLOCK_READ) { |
150 |
if (APR_STATUS_IS_EAGAIN(rv) && block == APR_NONBLOCK_READ) { |
148 |
rv = APR_SUCCESS; |
151 |
rv = APR_SUCCESS; |
149 |
} |
152 |
} |
150 |
return rv; |
153 |
goto cleanup; |
151 |
} |
154 |
} |
152 |
|
155 |
|
153 |
/* ### AP_MODE_PEEK is a horrific name for this mode because we also |
156 |
/* ### AP_MODE_PEEK is a horrific name for this mode because we also |
Lines 154-160
apr_status_t ap_core_input_filter(ap_filter_t *f,
Link Here
|
154 |
* eat any CRLFs that we see. That's not the obvious intention of |
157 |
* eat any CRLFs that we see. That's not the obvious intention of |
155 |
* this mode. Determine whether anyone actually uses this or not. */ |
158 |
* this mode. Determine whether anyone actually uses this or not. */ |
156 |
if (mode == AP_MODE_EATCRLF) { |
159 |
if (mode == AP_MODE_EATCRLF) { |
157 |
apr_bucket *e; |
|
|
158 |
const char *c; |
160 |
const char *c; |
159 |
|
161 |
|
160 |
/* The purpose of this loop is to ignore any CRLF (or LF) at the end |
162 |
/* The purpose of this loop is to ignore any CRLF (or LF) at the end |
Lines 167-182
apr_status_t ap_core_input_filter(ap_filter_t *f,
Link Here
|
167 |
* mean that there is another request, just a blank line. |
169 |
* mean that there is another request, just a blank line. |
168 |
*/ |
170 |
*/ |
169 |
while (1) { |
171 |
while (1) { |
170 |
if (APR_BRIGADE_EMPTY(ctx->b)) |
172 |
if (APR_BRIGADE_EMPTY(ctx->b)) { |
171 |
return APR_EOF; |
173 |
rv = APR_EOF; |
|
|
174 |
goto cleanup; |
175 |
} |
172 |
|
176 |
|
173 |
e = APR_BRIGADE_FIRST(ctx->b); |
177 |
e = APR_BRIGADE_FIRST(ctx->b); |
174 |
|
|
|
175 |
rv = apr_bucket_read(e, &str, &len, APR_NONBLOCK_READ); |
178 |
rv = apr_bucket_read(e, &str, &len, APR_NONBLOCK_READ); |
|
|
179 |
if (rv != APR_SUCCESS) { |
180 |
goto cleanup; |
181 |
} |
176 |
|
182 |
|
177 |
if (rv != APR_SUCCESS) |
|
|
178 |
return rv; |
179 |
|
180 |
c = str; |
183 |
c = str; |
181 |
while (c < str + len) { |
184 |
while (c < str + len) { |
182 |
if (*c == APR_ASCII_LF) |
185 |
if (*c == APR_ASCII_LF) |
Lines 184-190
apr_status_t ap_core_input_filter(ap_filter_t *f,
Link Here
|
184 |
else if (*c == APR_ASCII_CR && *(c + 1) == APR_ASCII_LF) |
187 |
else if (*c == APR_ASCII_CR && *(c + 1) == APR_ASCII_LF) |
185 |
c += 2; |
188 |
c += 2; |
186 |
else |
189 |
else |
187 |
return APR_SUCCESS; |
190 |
goto cleanup; |
188 |
} |
191 |
} |
189 |
|
192 |
|
190 |
/* If we reach here, we were a bucket just full of CRLFs, so |
193 |
/* If we reach here, we were a bucket just full of CRLFs, so |
Lines 192-198
apr_status_t ap_core_input_filter(ap_filter_t *f,
Link Here
|
192 |
/* FIXME: Is this the right thing to do in the core? */ |
195 |
/* FIXME: Is this the right thing to do in the core? */ |
193 |
apr_bucket_delete(e); |
196 |
apr_bucket_delete(e); |
194 |
} |
197 |
} |
195 |
return APR_SUCCESS; |
198 |
goto cleanup; |
196 |
} |
199 |
} |
197 |
|
200 |
|
198 |
/* If mode is EXHAUSTIVE, we want to just read everything until the end |
201 |
/* If mode is EXHAUSTIVE, we want to just read everything until the end |
Lines 206-213
apr_status_t ap_core_input_filter(ap_filter_t *f,
Link Here
|
206 |
* read, which means that it can pass it to the correct child process. |
209 |
* read, which means that it can pass it to the correct child process. |
207 |
*/ |
210 |
*/ |
208 |
if (mode == AP_MODE_EXHAUSTIVE) { |
211 |
if (mode == AP_MODE_EXHAUSTIVE) { |
209 |
apr_bucket *e; |
|
|
210 |
|
211 |
/* Tack on any buckets that were set aside. */ |
212 |
/* Tack on any buckets that were set aside. */ |
212 |
APR_BRIGADE_CONCAT(b, ctx->b); |
213 |
APR_BRIGADE_CONCAT(b, ctx->b); |
213 |
|
214 |
|
Lines 218-244
apr_status_t ap_core_input_filter(ap_filter_t *f,
Link Here
|
218 |
* must be EOS. */ |
219 |
* must be EOS. */ |
219 |
e = apr_bucket_eos_create(f->c->bucket_alloc); |
220 |
e = apr_bucket_eos_create(f->c->bucket_alloc); |
220 |
APR_BRIGADE_INSERT_TAIL(b, e); |
221 |
APR_BRIGADE_INSERT_TAIL(b, e); |
221 |
return APR_SUCCESS; |
222 |
goto cleanup; |
222 |
} |
223 |
} |
223 |
|
224 |
|
224 |
/* read up to the amount they specified. */ |
225 |
/* read up to the amount they specified. */ |
225 |
if (mode == AP_MODE_READBYTES || mode == AP_MODE_SPECULATIVE) { |
226 |
if (mode == AP_MODE_READBYTES || mode == AP_MODE_SPECULATIVE) { |
226 |
apr_bucket *e; |
|
|
227 |
|
228 |
AP_DEBUG_ASSERT(readbytes > 0); |
227 |
AP_DEBUG_ASSERT(readbytes > 0); |
229 |
|
228 |
|
230 |
e = APR_BRIGADE_FIRST(ctx->b); |
229 |
e = APR_BRIGADE_FIRST(ctx->b); |
231 |
rv = apr_bucket_read(e, &str, &len, block); |
230 |
rv = apr_bucket_read(e, &str, &len, block); |
232 |
|
231 |
|
233 |
if (APR_STATUS_IS_EAGAIN(rv) && block == APR_NONBLOCK_READ) { |
232 |
if (rv != APR_SUCCESS) { |
234 |
/* getting EAGAIN for a blocking read is an error; for a |
233 |
if (APR_STATUS_IS_EAGAIN(rv) && block == APR_NONBLOCK_READ) { |
235 |
* non-blocking read, return an empty brigade. */ |
234 |
/* getting EAGAIN for a blocking read is an error; for a |
236 |
return APR_SUCCESS; |
235 |
* non-blocking read, return an empty brigade. */ |
|
|
236 |
rv = APR_SUCCESS; |
237 |
} |
238 |
goto cleanup; |
237 |
} |
239 |
} |
238 |
else if (rv != APR_SUCCESS) { |
240 |
|
239 |
return rv; |
241 |
if (block == APR_BLOCK_READ && len == 0) { |
240 |
} |
|
|
241 |
else if (block == APR_BLOCK_READ && len == 0) { |
242 |
/* We wanted to read some bytes in blocking mode. We read |
242 |
/* We wanted to read some bytes in blocking mode. We read |
243 |
* 0 bytes. Hence, we now assume we are EOS. |
243 |
* 0 bytes. Hence, we now assume we are EOS. |
244 |
* |
244 |
* |
Lines 253-259
apr_status_t ap_core_input_filter(ap_filter_t *f,
Link Here
|
253 |
e = apr_bucket_eos_create(f->c->bucket_alloc); |
253 |
e = apr_bucket_eos_create(f->c->bucket_alloc); |
254 |
APR_BRIGADE_INSERT_TAIL(b, e); |
254 |
APR_BRIGADE_INSERT_TAIL(b, e); |
255 |
} |
255 |
} |
256 |
return APR_SUCCESS; |
256 |
goto cleanup; |
257 |
} |
257 |
} |
258 |
|
258 |
|
259 |
/* Have we read as much data as we wanted (be greedy)? */ |
259 |
/* Have we read as much data as we wanted (be greedy)? */ |
Lines 294-300
apr_status_t ap_core_input_filter(ap_filter_t *f,
Link Here
|
294 |
|
294 |
|
295 |
rv = apr_brigade_partition(ctx->b, readbytes, &e); |
295 |
rv = apr_brigade_partition(ctx->b, readbytes, &e); |
296 |
if (rv != APR_SUCCESS) { |
296 |
if (rv != APR_SUCCESS) { |
297 |
return rv; |
297 |
goto cleanup; |
298 |
} |
298 |
} |
299 |
|
299 |
|
300 |
/* Must do move before CONCAT */ |
300 |
/* Must do move before CONCAT */ |
Lines 312-318
apr_status_t ap_core_input_filter(ap_filter_t *f,
Link Here
|
312 |
{ |
312 |
{ |
313 |
rv = apr_bucket_copy(e, ©_bucket); |
313 |
rv = apr_bucket_copy(e, ©_bucket); |
314 |
if (rv != APR_SUCCESS) { |
314 |
if (rv != APR_SUCCESS) { |
315 |
return rv; |
315 |
APR_BRIGADE_CONCAT(ctx->b, ctx->tmpbb); |
|
|
316 |
goto cleanup; |
316 |
} |
317 |
} |
317 |
APR_BRIGADE_INSERT_TAIL(b, copy_bucket); |
318 |
APR_BRIGADE_INSERT_TAIL(b, copy_bucket); |
318 |
} |
319 |
} |
Lines 321-327
apr_status_t ap_core_input_filter(ap_filter_t *f,
Link Here
|
321 |
/* Take what was originally there and place it back on ctx->b */ |
322 |
/* Take what was originally there and place it back on ctx->b */ |
322 |
APR_BRIGADE_CONCAT(ctx->b, ctx->tmpbb); |
323 |
APR_BRIGADE_CONCAT(ctx->b, ctx->tmpbb); |
323 |
} |
324 |
} |
324 |
return APR_SUCCESS; |
325 |
|
|
|
326 |
cleanup: |
327 |
e = APR_BRIGADE_FIRST(ctx->b); |
328 |
if (e != APR_BRIGADE_SENTINEL(ctx->b) && e->length != (apr_size_t)-1) { |
329 |
f->c->data_in_input_filters |= 1; |
330 |
} |
331 |
return rv; |
325 |
} |
332 |
} |
326 |
|
333 |
|
327 |
static void setaside_remaining_output(ap_filter_t *f, |
334 |
static void setaside_remaining_output(ap_filter_t *f, |