]> granicus.if.org Git - apache/blob - server/util_xml.c
Complete the EBCDIC conversion support for XML documents.
[apache] / server / util_xml.c
1 /* Copyright 2000-2004 The Apache Software Foundation
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include "apr_xml.h"
17
18 #include "httpd.h"
19 #include "http_protocol.h"
20 #include "http_log.h"
21 #include "http_core.h"
22
23 #include "util_charset.h"
24 #include "util_xml.h"
25
26
27 /* used for reading input blocks */
28 #define READ_BLOCKSIZE 2048
29
30
31 AP_DECLARE(int) ap_xml_parse_input(request_rec * r, apr_xml_doc **pdoc)
32 {
33     apr_xml_parser *parser;
34     apr_bucket_brigade *brigade;
35     int seen_eos;
36     apr_status_t status;
37     char errbuf[200];
38     apr_size_t total_read = 0;
39     apr_size_t limit_xml_body = ap_get_limit_xml_body(r);
40     int result = HTTP_BAD_REQUEST;
41
42     parser = apr_xml_parser_create(r->pool);
43     brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
44
45     seen_eos = 0;
46     total_read = 0;
47
48     do {
49         apr_bucket *bucket;
50
51         /* read the body, stuffing it into the parser */
52         status = ap_get_brigade(r->input_filters, brigade,
53                                 AP_MODE_READBYTES, APR_BLOCK_READ,
54                                 READ_BLOCKSIZE);
55
56         if (status != APR_SUCCESS) {
57             goto read_error;
58         }
59
60         for (bucket = APR_BRIGADE_FIRST(brigade);
61              bucket != APR_BRIGADE_SENTINEL(brigade);
62              bucket = APR_BUCKET_NEXT(bucket))
63         {
64             const char *data;
65             apr_size_t len;
66
67             if (APR_BUCKET_IS_EOS(bucket)) {
68                 seen_eos = 1;
69                 break;
70             }
71
72             if (APR_BUCKET_IS_METADATA(bucket)) {
73                 continue;
74             }
75
76             status = apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
77             if (status != APR_SUCCESS) {
78                 goto read_error;
79             }
80
81             total_read += len;
82             if (limit_xml_body && total_read > limit_xml_body) {
83                 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
84                               "XML request body is larger than the configured "
85                               "limit of %lu", (unsigned long)limit_xml_body);
86                 result = HTTP_REQUEST_ENTITY_TOO_LARGE;
87                 goto read_error;
88             }
89
90             status = apr_xml_parser_feed(parser, data, len);
91             if (status) {
92                 goto parser_error;
93             }
94         }
95
96         apr_brigade_cleanup(brigade);
97     } while (!seen_eos);
98
99     apr_brigade_destroy(brigade);
100
101     /* tell the parser that we're done */
102     status = apr_xml_parser_done(parser, pdoc);
103     if (status) {
104         /* Some parsers are stupid and return an error on blank documents. */
105         if (!total_read) {
106             *pdoc = NULL;
107             return OK;
108         }
109         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
110                       "XML parser error (at end). status=%d", status);
111         return HTTP_BAD_REQUEST;
112     }
113
114 #if APR_CHARSET_EBCDIC
115     apr_xml_parser_convert_doc(r->pool, *pdoc, ap_hdrs_from_ascii);
116 #endif
117     return OK;
118
119   parser_error:
120     (void) apr_xml_parser_geterror(parser, errbuf, sizeof(errbuf));
121     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
122                   "%s", errbuf);
123
124     /* FALLTHRU */
125
126   read_error:
127     /* make sure the parser is terminated */
128     (void) apr_xml_parser_done(parser, NULL);
129
130     apr_brigade_destroy(brigade);
131
132     /* Apache will supply a default error, plus the error log above. */
133     return result;
134 }