Apache HTTPD
mod_xml2enc.c
Go to the documentation of this file.
1/* Copyright (c) 2007-11, WebThing Ltd
2 * Copyright (c) 2011-, The Apache Software Foundation
3 *
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership.
7 * The ASF licenses this file to You under the Apache License, Version 2.0
8 * (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#if defined(WIN32)
21#define XML2ENC_DECLARE_EXPORT
22#endif
23
24#include <ctype.h>
25
26/* libxml2 includes unicode/[...].h files which uses C++ comments */
27#if defined(__clang__)
28#pragma clang diagnostic push
29#pragma clang diagnostic warning "-Wcomment"
30#elif defined(__GNUC__)
31#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
32#pragma GCC diagnostic push
33#pragma GCC diagnostic warning "-Wcomment"
34#endif
35#endif
36
37/* libxml2 */
38#include <libxml/encoding.h>
39
40#if defined(__clang__)
41#pragma clang diagnostic pop
42#elif defined(__GNUC__)
43#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
44#pragma GCC diagnostic pop
45#endif
46#endif
47
48#include "http_protocol.h"
49#include "http_config.h"
50#include "http_log.h"
51#include "apr_strings.h"
52#include "apr_xlate.h"
53
54#include "apr_optional.h"
55#include "mod_xml2enc.h"
56
57module AP_MODULE_DECLARE_DATA xml2enc_module;
58
59#define BUFLEN 8192
60#define BUF_MIN 4096
61#define APR_BRIGADE_DO(b,bb) for (b = APR_BRIGADE_FIRST(bb); \
62 b != APR_BRIGADE_SENTINEL(bb); \
63 b = APR_BUCKET_NEXT(b))
64
65#define ENC_INITIALISED 0x100
66#define ENC_SEEN_EOS 0x200
67#define ENC_SKIPTO ENCIO_SKIPTO
68
69#define HAVE_ENCODING(enc) \
70 (((enc)!=XML_CHAR_ENCODING_NONE)&&((enc)!=XML_CHAR_ENCODING_ERROR))
71
72/*
73 * XXX: Check all those ap_assert()s and replace those that should not happen
74 * XXX: with AP_DEBUG_ASSERT and those that may happen with proper error
75 * XXX: handling.
76 */
88
94
95typedef struct {
96 const char* val;
97} tattr;
98
101
102static apr_status_t xml2enc_filter(request_rec* r, const char* enc,
103 unsigned int mode)
104{
105 /* set up a ready-initialised ctx to convert to enc, and insert filter */
106 apr_xlate_t* convset;
107 apr_status_t rv;
108 unsigned int flags = (mode ^ ENCIO);
109 if ((mode & ENCIO) == ENCIO_OUTPUT) {
110 rv = apr_xlate_open(&convset, enc, "UTF-8", r->pool);
112 }
113 else if ((mode & ENCIO) == ENCIO_INPUT) {
114 rv = apr_xlate_open(&convset, "UTF-8", enc, r->pool);
116 }
117 else if ((mode & ENCIO) == ENCIO_INPUT_CHECKS) {
118 convset = NULL;
119 rv = APR_SUCCESS; /* we'll initialise later by sniffing */
120 }
121 else {
122 rv = APR_EGENERAL;
124 "xml2enc: bad mode %x", mode);
125 }
126 if (rv == APR_SUCCESS) {
127 xml2ctx* ctx = apr_pcalloc(r->pool, sizeof(xml2ctx));
128 ctx->flags = flags;
129 if (flags & ENC_INITIALISED) {
130 ctx->convset = convset;
131 ctx->bblen = BUFLEN;
132 ctx->buf = apr_palloc(r->pool, (apr_size_t)ctx->bblen);
133 }
134 ap_add_output_filter("xml2enc", ctx, r, r->connection);
135 }
136 else {
138 "xml2enc: Charset %s not supported.", enc) ;
139 }
140 return rv;
141}
142
143/* This needs to operate only when we're using htmlParser */
144/* Different modules may apply different rules here. Ho, hum. */
146{
147 apr_status_t rv;
148 xml2cfg* cfg = ap_get_module_config(r->per_dir_config, &xml2enc_module);
149 if ((cfg->skipto != NULL) && (ctx->flags & ENC_SKIPTO)) {
150 int found = 0;
151 char* p = ap_strchr(ctx->buf, '<');
152 tattr* starts = (tattr*) cfg->skipto->elts;
153 while (!found && p && *p) {
154 int i;
155 for (i = 0; i < cfg->skipto->nelts; ++i) {
156 if (!strncasecmp(p+1, starts[i].val, strlen(starts[i].val))) {
157 /* found a starting element. Strip all that comes before. */
158 apr_bucket* b;
160 rv = apr_brigade_partition(ctx->bbsave, (p-ctx->buf),
161 &bstart);
162 ap_assert(rv == APR_SUCCESS);
163 while (b = APR_BRIGADE_FIRST(ctx->bbsave), b != bstart) {
165 }
166 ctx->bytes -= (p-ctx->buf);
167 ctx->buf = p ;
168 found = 1;
170 "Skipped to first <%s> element",
171 starts[i].val) ;
172 break;
173 }
174 }
175 p = ap_strchr(p+1, '<');
176 }
177 if (p == NULL) {
179 "Failed to find start of recognised HTML!");
180 }
181 }
182}
184{
185 xml2cfg* cfg = NULL; /* initialise to shut compiler warnings up */
186 char* p ;
189 apr_bucket* b;
191 apr_status_t rv;
192 const char* ctype = r->content_type;
193
194 if (ctype) {
196 "Content-Type is %s", ctype) ;
197
198 /* If we've got it in the HTTP headers, there's nothing to do */
199 if (ctype && (p = ap_strcasestr(ctype, "charset=") , p != NULL)) {
200 p += 8 ;
201 if (ctx->encoding = apr_pstrndup(r->pool, p, strcspn(p, " ;") ),
202 ctx->encoding) {
204 "Got charset %s from HTTP headers", ctx->encoding) ;
205 ctx->xml2enc = xmlParseCharEncoding(ctx->encoding);
206 }
207 }
208 }
209
210 /* to sniff, first we look for BOM */
211 if (ctx->xml2enc == XML_CHAR_ENCODING_NONE) {
212 ctx->xml2enc = xmlDetectCharEncoding((const unsigned char*)ctx->buf,
213 ctx->bytes);
214 if (HAVE_ENCODING(ctx->xml2enc)) {
216 "Got charset from XML rules.") ;
217 ctx->encoding = xmlGetCharEncodingName(ctx->xml2enc);
218 }
219 }
220
221 /* If none of the above, look for a META-thingey */
222 /* also we're probably about to invalidate it, so we remove it. */
223 if (ap_regexec(seek_meta_ctype, ctx->buf, 1, match, 0) == 0 ) {
224 /* get markers on the start and end of the match */
225 rv = apr_brigade_partition(ctx->bbsave, match[0].rm_eo, &cute);
226 ap_assert(rv == APR_SUCCESS);
227 rv = apr_brigade_partition(ctx->bbsave, match[0].rm_so, &cutb);
228 ap_assert(rv == APR_SUCCESS);
229 /* now set length of useful buf for start-of-data hooks */
230 ctx->bytes = match[0].rm_so;
231 if (ctx->encoding == NULL) {
232 p = apr_pstrndup(r->pool, ctx->buf + match[0].rm_so,
233 match[0].rm_eo - match[0].rm_so) ;
234 if (ap_regexec(seek_charset, p, 2, match, 0) == 0) {
235 if (ctx->encoding = apr_pstrndup(r->pool, p+match[1].rm_so,
236 match[1].rm_eo - match[1].rm_so),
237 ctx->encoding) {
238 ctx->xml2enc = xmlParseCharEncoding(ctx->encoding);
239 if (HAVE_ENCODING(ctx->xml2enc))
241 "Got charset %s from HTML META", ctx->encoding) ;
242 }
243 }
244 }
245
246 /* cut out the <meta> we're invalidating */
247 while (cutb != cute) {
250 cutb = b;
251 }
252 /* and leave a string */
253 ctx->buf[ctx->bytes] = 0;
254 }
255
256 /* either it's set to something we found or it's still the default */
257 /* Aaargh! libxml2 has undocumented <META-crap> support. So this fails
258 * if metafix is not active. Have to make it conditional.
259 *
260 * No, that means no-metafix breaks things. Deal immediately with
261 * this particular instance of metafix.
262 */
263 if (!HAVE_ENCODING(ctx->xml2enc)) {
264 cfg = ap_get_module_config(r->per_dir_config, &xml2enc_module);
265 if (!ctx->encoding) {
266 ctx->encoding = cfg->default_charset?cfg->default_charset:"ISO-8859-1";
267 }
268 /* Unsupported charset. Can we get (iconv) support through apr_xlate? */
270 "Charset %s not supported by libxml2; trying apr_xlate",
271 ctx->encoding);
272 if (apr_xlate_open(&ctx->convset, "UTF-8", ctx->encoding, r->pool)
273 == APR_SUCCESS) {
274 ctx->xml2enc = XML_CHAR_ENCODING_UTF8 ;
275 } else {
277 "Charset %s not supported. Consider aliasing it?",
278 ctx->encoding) ;
279 }
280 }
281
282 if (!HAVE_ENCODING(ctx->xml2enc)) {
283 /* Use configuration default as a last resort */
285 "No usable charset information; using configuration default");
286 ctx->xml2enc = (cfg->default_encoding == XML_CHAR_ENCODING_NONE)
288 }
289 if (ctype && ctx->encoding) {
290 if (ap_regexec(seek_charset, ctype, 2, match, 0)) {
291 r->content_type = apr_pstrcat(r->pool, ctype, ";charset=utf-8",
292 NULL);
293 } else {
294 char* str = apr_palloc(r->pool, strlen(r->content_type) + 13
295 - (match[0].rm_eo - match[0].rm_so) + 1);
296 memcpy(str, r->content_type, match[1].rm_so);
297 memcpy(str + match[1].rm_so, "utf-8", 5);
298 strcpy(str + match[1].rm_so + 5, r->content_type+match[1].rm_eo);
299 r->content_type = str;
300 }
301 }
302}
303
305{
306 xml2ctx* ctx;
307 if (!f->ctx) {
308 xml2cfg* cfg = ap_get_module_config(f->r->per_dir_config,
309 &xml2enc_module);
310 f->ctx = ctx = apr_pcalloc(f->r->pool, sizeof(xml2ctx));
311 ctx->xml2enc = XML_CHAR_ENCODING_NONE;
312 if (cfg->skipto != NULL) {
313 ctx->flags |= ENC_SKIPTO;
314 }
315 }
316 return APR_SUCCESS;
317}
319{
320 xml2ctx* ctx = f->ctx;
321 apr_status_t rv;
322 apr_bucket* b;
324 apr_size_t insz = 0;
325 int pending_meta = 0;
326 char *mtype;
327 char *p;
328
329 if (!ctx || !f->r->content_type) {
330 /* log error about configuring this */
332 return ap_pass_brigade(f->next, bb) ;
333 }
334
335 /* Extract the media type, ignoring parameters in content-type. */
336 mtype = apr_pstrdup(f->r->pool, f->r->content_type);
337 if ((p = ap_strchr(mtype, ';')) != NULL) *p = '\0';
339
340 /* Accept text/ types, plus any XML media type per RFC 7303. */
341 if (!(strncmp(mtype, "text/", 5) == 0
342 || strcmp(mtype, "application/xml") == 0
343 || (strlen(mtype) > 7 /* minimum 'a/b+xml' length */
344 && (p = strstr(mtype, "+xml")) != NULL
345 && strlen(p) == 4 /* ensures +xml is a suffix */))) {
347 return ap_pass_brigade(f->next, bb) ;
348 }
349
350 if (ctx->bbsave == NULL) {
351 ctx->bbsave = apr_brigade_create(f->r->pool,
352 f->r->connection->bucket_alloc);
353 }
354 /* append to any data left over from last time */
355 APR_BRIGADE_CONCAT(ctx->bbsave, bb);
356
357 if (!(ctx->flags & ENC_INITIALISED)) {
358 /* some kind of initialisation required */
359 /* Turn all this off when post-processing */
360
361 /* if we don't have enough data to sniff but more's to come, wait */
362 apr_brigade_length(ctx->bbsave, 0, &ctx->bblen);
363 if ((ctx->bblen < BUF_MIN) && (ctx->bblen != -1)) {
364 APR_BRIGADE_DO(b, ctx->bbsave) {
365 if (APR_BUCKET_IS_EOS(b)) {
366 ctx->flags |= ENC_SEEN_EOS;
367 break;
368 }
369 }
370 if (!(ctx->flags & ENC_SEEN_EOS)) {
371 /* not enough data to sniff. Wait for more */
372 APR_BRIGADE_DO(b, ctx->bbsave) {
373 rv = apr_bucket_setaside(b, f->r->pool);
374 ap_assert(rv == APR_SUCCESS);
375 }
376 return APR_SUCCESS;
377 }
378 }
379 if (ctx->bblen == -1) {
380 ctx->bblen = BUFLEN-1;
381 }
382
383 /* flatten it into a NULL-terminated string */
384 ctx->buf = apr_palloc(f->r->pool, (apr_size_t)(ctx->bblen+1));
385 ctx->bytes = (apr_size_t)ctx->bblen;
386 rv = apr_brigade_flatten(ctx->bbsave, ctx->buf, &ctx->bytes);
387 ap_assert(rv == APR_SUCCESS);
388 ctx->buf[ctx->bytes] = 0;
389 sniff_encoding(f->r, ctx);
390
391 /* FIXME: hook here for rewriting start-of-data? */
392 /* nah, we only have one action here - call it inline */
393 fix_skipto(f->r, ctx);
394
395 /* we might change the Content-Length, so let's force its re-calculation */
396 apr_table_unset(f->r->headers_out, "Content-Length");
397
398 /* consume the data we just sniffed */
399 /* we need to omit any <meta> we just invalidated */
400 ctx->flags |= ENC_INITIALISED;
401 ap_set_module_config(f->r->request_config, &xml2enc_module, ctx);
402 }
403 if (ctx->bbnext == NULL) {
404 ctx->bbnext = apr_brigade_create(f->r->pool,
405 f->r->connection->bucket_alloc);
406 }
407
408 if (!ctx->convset) {
409 rv = ap_pass_brigade(f->next, ctx->bbsave);
410 apr_brigade_cleanup(ctx->bbsave);
412 return rv;
413 }
414 /* move the data back to bb */
415 APR_BRIGADE_CONCAT(bb, ctx->bbsave);
416
417 while (!APR_BRIGADE_EMPTY(bb)) {
418 b = APR_BRIGADE_FIRST(bb);
419 ctx->bytes = 0;
422 APR_BRIGADE_INSERT_TAIL(ctx->bbnext, b);
423 /* Besides FLUSH, aggregate meta buckets to send them at
424 * once below. This resource filter is over on EOS.
425 */
426 pending_meta = 1;
427 if (APR_BUCKET_IS_EOS(b)) {
429 APR_BRIGADE_CONCAT(ctx->bbnext, bb);
430 }
431 else if (!APR_BUCKET_IS_FLUSH(b)) {
432 continue;
433 }
434 }
435 if (pending_meta) {
436 pending_meta = 0;
437 /* passing meta bucket down the chain */
438 rv = ap_pass_brigade(f->next, ctx->bbnext);
439 apr_brigade_cleanup(ctx->bbnext);
440 if (rv != APR_SUCCESS) {
441 return rv;
442 }
443 continue;
444 }
445 /* data bucket */
446 {
447 char* buf;
448 apr_size_t bytes = 0;
449 char fixbuf[BUFLEN];
451 if (insz > 0) { /* we have dangling data. Flatten it. */
452 buf = fixbuf;
453 bytes = BUFLEN;
454 rv = apr_brigade_flatten(bb, buf, &bytes);
455 ap_assert(rv == APR_SUCCESS);
456 if (bytes == insz) {
457 /* this is only what we've already tried to convert.
458 * The brigade is exhausted.
459 * Save remaining data for next time round
460 */
461
463 "xml2enc: Setting aside %" APR_SIZE_T_FMT
464 " unconverted bytes", bytes);
465 rv = ap_fflush(f->next, ctx->bbnext);
466 APR_BRIGADE_CONCAT(ctx->bbsave, bb);
467 APR_BRIGADE_DO(b, ctx->bbsave) {
469 == APR_SUCCESS);
470 }
471 return rv;
472 }
473 /* remove the data we've just read */
475 while (b = APR_BRIGADE_FIRST(bb), b != bstart) {
477 }
479 "xml2enc: consuming %" APR_SIZE_T_FMT
480 " bytes flattened", bytes);
481 }
482 else {
483 rv = apr_bucket_read(b, (const char**)&buf, &bytes,
486 bdestroy = b; /* can't destroy until finished with the data */
488 "xml2enc: consuming %" APR_SIZE_T_FMT
489 " bytes from bucket", bytes);
490 }
491 /* OK, we've got some input we can use in [buf,bytes] */
492 if (rv == APR_SUCCESS) {
495 consumed = insz = bytes;
496 while (insz > 0) {
498 if (ctx->bytes == ctx->bblen) {
499 /* nothing was converted last time!
500 * break out of this loop!
501 */
503 bb->bucket_alloc);
506 "xml2enc: reinserting %" APR_SIZE_T_FMT
507 " unconsumed bytes from bucket", insz);
508 break;
509 }
510 ctx->bytes = (apr_size_t)ctx->bblen;
511 rv = apr_xlate_conv_buffer(ctx->convset, buf+(bytes - insz),
512 &insz, ctx->buf, &ctx->bytes);
514 "xml2enc: converted %" APR_SIZE_T_FMT
515 "/%" APR_OFF_T_FMT " bytes", consumed - insz,
516 ctx->bblen - ctx->bytes);
517 consumed = insz;
518 rv2 = ap_fwrite(f->next, ctx->bbnext, ctx->buf,
519 (apr_size_t)ctx->bblen - ctx->bytes);
520 if (rv2 != APR_SUCCESS) {
522 "ap_fwrite failed");
523 return rv2;
524 }
525 switch (rv) {
526 case APR_SUCCESS:
527 continue;
528 case APR_EINCOMPLETE:
530 "INCOMPLETE");
531 continue; /* If outbuf too small, go round again.
532 * If it was inbuf, we'll break out when
533 * we test ctx->bytes == ctx->bblen
534 */
535 case APR_EINVAL: /* try skipping one bad byte */
537 "Skipping invalid byte(s) in input stream!");
538 --insz;
539 continue;
540 default:
541 /* Erk! What's this?
542 * Bail out, flush, and hope to eat the buf raw
543 */
545 "Failed to convert input; trying it raw") ;
546 ctx->convset = NULL;
547 rv = ap_fflush(f->next, ctx->bbnext);
548 if (rv != APR_SUCCESS)
550 "ap_fflush failed");
551 apr_brigade_cleanup(ctx->bbnext);
552 }
553 }
554 } else {
556 "xml2enc: error reading data") ;
557 }
558 if (bdestroy)
560 if (rv != APR_SUCCESS)
561 return rv;
562 }
563 }
564 if (pending_meta) {
565 /* passing pending meta bucket down the chain before leaving */
566 rv = ap_pass_brigade(f->next, ctx->bbnext);
567 apr_brigade_cleanup(ctx->bbnext);
568 if (rv != APR_SUCCESS) {
569 return rv;
570 }
571 }
572
573 return APR_SUCCESS;
574}
575
577 const char** encoding)
578{
579 xml2ctx* ctx = ap_get_module_config(r->request_config, &xml2enc_module);
580 if (!ctx || !(ctx->flags & ENC_INITIALISED)) {
581 return APR_EAGAIN;
582 }
583 *encp = ctx->xml2enc;
584 *encoding = ctx->encoding;
585 return HAVE_ENCODING(ctx->xml2enc) ? APR_SUCCESS : APR_EGENERAL;
586}
587
588#define PROTO_FLAGS AP_FILTER_PROTO_CHANGE|AP_FILTER_PROTO_CHANGE_LENGTH
602static const char* set_alias(cmd_parms* cmd, void* CFG,
603 const char* charset, const char* alias)
604{
605 const char* errmsg = ap_check_cmd_context(cmd, GLOBAL_ONLY);
606 if (errmsg != NULL)
607 return errmsg ;
608 else if (xmlAddEncodingAlias(charset, alias) == 0)
609 return NULL;
610 else
611 return "Error setting charset alias";
612}
613
614static const char* set_default(cmd_parms* cmd, void* CFG, const char* charset)
615{
616 xml2cfg* cfg = CFG;
617 cfg->default_charset = charset;
619 switch(cfg->default_encoding) {
621 return "Default charset not found";
623 return "Invalid or unsupported default charset";
624 default:
625 return NULL;
626 }
627}
628static const char* set_skipto(cmd_parms* cmd, void* CFG, const char* arg)
629{
630 tattr* attr;
631 xml2cfg* cfg = CFG;
632 if (cfg->skipto == NULL)
633 cfg->skipto = apr_array_make(cmd->pool, 4, sizeof(tattr));
634 attr = apr_array_push(cfg->skipto) ;
635 attr->val = arg;
636 return NULL;
637}
638
639static const command_rec xml2enc_cmds[] = {
640 AP_INIT_TAKE1("xml2EncDefault", set_default, NULL, OR_ALL,
641 "Usage: xml2EncDefault charset"),
642 AP_INIT_ITERATE2("xml2EncAlias", set_alias, NULL, RSRC_CONF,
643 "EncodingAlias charset alias [more aliases]"),
644 AP_INIT_ITERATE("xml2StartParse", set_skipto, NULL, OR_ALL,
645 "Ignore anything in front of the first of these elements"),
646 { NULL }
647};
648static void* xml2enc_config(apr_pool_t* pool, char* x)
649{
650 xml2cfg* ret = apr_pcalloc(pool, sizeof(xml2cfg));
651 ret->default_encoding = XML_CHAR_ENCODING_NONE ;
652 return ret;
653}
654
655static void* xml2enc_merge(apr_pool_t* pool, void* BASE, void* ADD)
656{
657 xml2cfg* base = BASE;
658 xml2cfg* add = ADD;
659 xml2cfg* ret = apr_pcalloc(pool, sizeof(xml2cfg));
660 ret->default_encoding = (add->default_encoding == XML_CHAR_ENCODING_NONE)
661 ? base->default_encoding : add->default_encoding ;
662 ret->default_charset = add->default_charset
663 ? add->default_charset : base->default_charset;
664 ret->skipto = add->skipto ? add->skipto : base->skipto;
665 return ret;
666}
667
672 NULL,
673 NULL,
676};
677
679 (ap_filter_t *f, char** bufp, apr_size_t* bytesp),
int int const char ** match
Definition ap_regex.h:279
#define AP_REG_ICASE
Definition ap_regex.h:73
#define AP_REG_EXTENDED
Definition ap_regex.h:78
char * strstr(char *s1, char *s2)
APR-UTIL registration of functions exported by modules.
APR Strings library.
APR I18N translation library.
return found
Definition core.c:2840
#define AP_INIT_TAKE1(directive, func, mconfig, where, help)
#define ap_get_module_config(v, m)
#define AP_INIT_ITERATE2(directive, func, mconfig, where, help)
#define AP_DECLARE_MODULE(foo)
ap_conf_vector_t * base
#define AP_INIT_ITERATE(directive, func, mconfig, where, help)
#define ap_set_module_config(v, m, val)
request_rec * r
#define DECLINED
Definition httpd.h:457
#define OK
Definition httpd.h:456
#define ap_fwrite(f, bb, data, nbyte)
apr_status_t ap_fflush(ap_filter_t *f, apr_bucket_brigade *bb)
ap_filter_rec_t * ap_register_output_filter_protocol(const char *name, ap_out_filter_func filter_func, ap_init_filter_func filter_init, ap_filter_type ftype, unsigned int proto_flags)
apr_status_t ap_pass_brigade(ap_filter_t *filter, apr_bucket_brigade *bucket)
ap_filter_t * ap_add_output_filter(const char *name, void *ctx, request_rec *r, conn_rec *c)
void ap_remove_output_filter(ap_filter_t *f)
@ AP_FTYPE_RESOURCE
#define APLOGNO(n)
Definition http_log.h:117
#define APLOG_INFO
Definition http_log.h:70
#define ap_log_rerror
Definition http_log.h:454
#define APLOG_ERR
Definition http_log.h:67
#define APLOG_MARK
Definition http_log.h:283
#define APLOG_WARNING
Definition http_log.h:68
#define APLOG_DEBUG
Definition http_log.h:71
const unsigned char * buf
Definition util_md5.h:50
void const char * arg
Definition http_vhost.h:63
#define APR_EAGAIN
Definition apr_errno.h:730
#define APR_EGENERAL
Definition apr_errno.h:313
#define APR_EINCOMPLETE
Definition apr_errno.h:328
#define APR_EINVAL
Definition apr_errno.h:711
apr_file_t * f
#define APR_BUCKET_IS_FLUSH(e)
#define APR_BUCKET_REMOVE(e)
#define APR_BUCKET_IS_METADATA(e)
#define APR_BRIGADE_INSERT_TAIL(b, e)
#define APR_BRIGADE_INSERT_HEAD(b, e)
#define APR_BUCKET_NEXT(e)
#define APR_BRIGADE_CONCAT(a, b)
#define APR_BRIGADE_EMPTY(b)
#define apr_bucket_delete(e)
#define APR_BUCKET_IS_EOS(e)
apr_brigade_flush void * ctx
#define apr_bucket_setaside(e, p)
#define APR_BRIGADE_FIRST(b)
#define apr_bucket_read(e, str, len, block)
#define apr_bucket_destroy(e)
@ APR_BLOCK_READ
Definition apr_buckets.h:58
apr_dbd_transaction_t int mode
Definition apr_dbd.h:261
const char apr_ssize_t int flags
Definition apr_encode.h:168
#define APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ns, link, ret, name, args_decl, args_use, ok, decline)
#define APR_REGISTER_OPTIONAL_FN(name)
struct apr_xlate_t apr_xlate_t
Definition apr_xlate.h:39
#define OR_ALL
#define RSRC_CONF
#define STANDARD20_MODULE_STUFF
#define ap_strchr(s, c)
Definition httpd.h:2351
char * ap_strcasestr(const char *s1, const char *s2)
Definition util.c:289
void ap_str_tolower(char *s)
Definition util.c:2410
#define ap_assert(exp)
Definition httpd.h:2271
ap_regex_t * ap_pregcomp(apr_pool_t *p, const char *pattern, int cflags)
Definition util.c:262
#define GLOBAL_ONLY
const char * ap_check_cmd_context(cmd_parms *cmd, unsigned forbidden)
Definition core.c:1301
apr_size_t size
apr_uint32_t val
Definition apr_atomic.h:66
const char int apr_pool_t * pool
Definition apr_cstr.h:84
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
int strncasecmp(const char *a, const char *b, size_t n)
apr_pool_t * b
Definition apr_pools.h:529
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
const void apr_size_t bytes
Definition apr_random.h:91
const char const char *const const char *const apr_procattr_t * attr
apr_cmdtype_e cmd
Apache Configuration.
Apache Logging library.
HTTP protocol handling.
apr_pool_t * p
Definition md_event.c:32
static apr_status_t(* xml2enc_filter)(request_rec *, const char *, unsigned int)
static apr_status_t(* xml2enc_charset)(request_rec *, xmlCharEncoding *, const char **)
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
static apr_status_t xml2enc_ffunc(ap_filter_t *f, apr_bucket_brigade *bb)
static ap_regex_t * seek_charset
static void * xml2enc_merge(apr_pool_t *pool, void *BASE, void *ADD)
int xml2enc_run_preprocess(ap_filter_t *f, char **bufp, apr_size_t *bytesp)
static void sniff_encoding(request_rec *r, xml2ctx *ctx)
static const char * set_alias(cmd_parms *cmd, void *CFG, const char *charset, const char *alias)
static const char * set_skipto(cmd_parms *cmd, void *CFG, const char *arg)
static void * xml2enc_config(apr_pool_t *pool, char *x)
#define PROTO_FLAGS
#define BUF_MIN
Definition mod_xml2enc.c:60
#define ENC_INITIALISED
Definition mod_xml2enc.c:65
static void fix_skipto(request_rec *r, xml2ctx *ctx)
#define HAVE_ENCODING(enc)
Definition mod_xml2enc.c:69
static const char * set_default(cmd_parms *cmd, void *CFG, const char *charset)
#define ENC_SEEN_EOS
Definition mod_xml2enc.c:66
static ap_regex_t * seek_meta_ctype
Definition mod_xml2enc.c:99
#define BUFLEN
Definition mod_xml2enc.c:59
static void xml2enc_hooks(apr_pool_t *pool)
#define ENC_SKIPTO
Definition mod_xml2enc.c:67
#define APR_BRIGADE_DO(b, bb)
Definition mod_xml2enc.c:61
static apr_status_t xml2enc_filter_init(ap_filter_t *f)
static const command_rec xml2enc_cmds[]
#define ENCIO_INPUT
Definition mod_xml2enc.h:20
#define ENCIO
Definition mod_xml2enc.h:23
#define ENCIO_INPUT_CHECKS
Definition mod_xml2enc.h:22
#define ENCIO_OUTPUT
Definition mod_xml2enc.h:21
The representation of a filter chain.
apr_bucket_alloc_t * bucket_alloc
apr_pool_t * pool
A structure that represents the current request.
Definition httpd.h:845
const char * content_type
Definition httpd.h:992
apr_pool_t * pool
Definition httpd.h:847
conn_rec * connection
Definition httpd.h:849
struct ap_conf_vector_t * request_config
Definition httpd.h:1049
struct ap_conf_vector_t * per_dir_config
Definition httpd.h:1047
apr_array_header_t * skipto
Definition mod_xml2enc.c:92
const char * default_charset
Definition mod_xml2enc.c:90
xmlCharEncoding default_encoding
Definition mod_xml2enc.c:91
apr_xlate_t * convset
Definition mod_xml2enc.c:81
apr_off_t bblen
Definition mod_xml2enc.c:83
char * buf
Definition mod_xml2enc.c:79
apr_bucket_brigade * bbnext
Definition mod_xml2enc.c:84
unsigned int flags
Definition mod_xml2enc.c:82
const char * encoding
Definition mod_xml2enc.c:86
apr_size_t bytes
Definition mod_xml2enc.c:80
xmlCharEncoding xml2enc
Definition mod_xml2enc.c:78
apr_bucket_brigade * bbsave
Definition mod_xml2enc.c:85
#define str