842ae4bd224140319ae7feec1872b93dfd491143fielding/* Licensed to the Apache Software Foundation (ASF) under one or more
842ae4bd224140319ae7feec1872b93dfd491143fielding * contributor license agreements. See the NOTICE file distributed with
842ae4bd224140319ae7feec1872b93dfd491143fielding * this work for additional information regarding copyright ownership.
842ae4bd224140319ae7feec1872b93dfd491143fielding * The ASF licenses this file to You under the Apache License, Version 2.0
842ae4bd224140319ae7feec1872b93dfd491143fielding * (the "License"); you may not use this file except in compliance with
842ae4bd224140319ae7feec1872b93dfd491143fielding * the License. You may obtain a copy of the License at
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * http://www.apache.org/licenses/LICENSE-2.0
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * Unless required by applicable law or agreed to in writing, software
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * distributed under the License is distributed on an "AS IS" BASIS,
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * See the License for the specific language governing permissions and
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * limitations under the License.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
aa552377469071a421252dab6568c204a99cf770gstein#include "apr_xml.h"
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "httpd.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "http_protocol.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "http_log.h"
cd5c0afc86ca2eb23d6d12e14590e03cf2f80450gstein#include "http_core.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein
c364a517c4f0db3d0a33c662c02f2d567a33e135martin#include "util_charset.h"
f6b86fd524444dacf82f64148300d8be04918314gstein#include "util_xml.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f69b31136266022effeb1272d153c92a09de072djerenkrantz/* used for reading input blocks */
f69b31136266022effeb1272d153c92a09de072djerenkrantz#define READ_BLOCKSIZE 2048
f6b86fd524444dacf82f64148300d8be04918314gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein
7184de27ec1d62a83c41cdeac0953ca9fd661e8csf/* we know core's module_index is 0 */
7184de27ec1d62a83c41cdeac0953ca9fd661e8csf#undef APLOG_MODULE_INDEX
7184de27ec1d62a83c41cdeac0953ca9fd661e8csf#define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
36ef8f77bffe75d1aa327882be1b5bdbe2ff567asf
aa552377469071a421252dab6568c204a99cf770gsteinAP_DECLARE(int) ap_xml_parse_input(request_rec * r, apr_xml_doc **pdoc)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
aa552377469071a421252dab6568c204a99cf770gstein apr_xml_parser *parser;
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz apr_bucket_brigade *brigade;
3a02a42c92afc04c1cfca12eabdf19963784ae83nd int seen_eos;
aa552377469071a421252dab6568c204a99cf770gstein apr_status_t status;
aa552377469071a421252dab6568c204a99cf770gstein char errbuf[200];
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz apr_size_t total_read = 0;
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz apr_size_t limit_xml_body = ap_get_limit_xml_body(r);
226b4a760e9b997415cf061bb3d979c0c31ae642jorton int result = HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
aa552377469071a421252dab6568c204a99cf770gstein parser = apr_xml_parser_create(r->pool);
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz seen_eos = 0;
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz total_read = 0;
f69b31136266022effeb1272d153c92a09de072djerenkrantz
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz do {
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz apr_bucket *bucket;
f69b31136266022effeb1272d153c92a09de072djerenkrantz
f69b31136266022effeb1272d153c92a09de072djerenkrantz /* read the body, stuffing it into the parser */
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz status = ap_get_brigade(r->input_filters, brigade,
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz AP_MODE_READBYTES, APR_BLOCK_READ,
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz READ_BLOCKSIZE);
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz if (status != APR_SUCCESS) {
1715880355ef7f574cae2e8f973411b51acededeylavic result = ap_map_http_request_error(status, HTTP_BAD_REQUEST);
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz goto read_error;
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz }
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz
2e7ef6efb7164346000607d5b5c2d2d392d1a5eajwoolley for (bucket = APR_BRIGADE_FIRST(brigade);
2e7ef6efb7164346000607d5b5c2d2d392d1a5eajwoolley bucket != APR_BRIGADE_SENTINEL(brigade);
2e7ef6efb7164346000607d5b5c2d2d392d1a5eajwoolley bucket = APR_BUCKET_NEXT(bucket))
2e7ef6efb7164346000607d5b5c2d2d392d1a5eajwoolley {
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz const char *data;
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz apr_size_t len;
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz if (APR_BUCKET_IS_EOS(bucket)) {
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz seen_eos = 1;
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz break;
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz }
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz if (APR_BUCKET_IS_METADATA(bucket)) {
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz continue;
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz }
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz status = apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz if (status != APR_SUCCESS) {
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz goto read_error;
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz }
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz
f69b31136266022effeb1272d153c92a09de072djerenkrantz total_read += len;
f69b31136266022effeb1272d153c92a09de072djerenkrantz if (limit_xml_body && total_read > limit_xml_body) {
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00539)
f69b31136266022effeb1272d153c92a09de072djerenkrantz "XML request body is larger than the configured "
f69b31136266022effeb1272d153c92a09de072djerenkrantz "limit of %lu", (unsigned long)limit_xml_body);
226b4a760e9b997415cf061bb3d979c0c31ae642jorton result = HTTP_REQUEST_ENTITY_TOO_LARGE;
f69b31136266022effeb1272d153c92a09de072djerenkrantz goto read_error;
f69b31136266022effeb1272d153c92a09de072djerenkrantz }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz status = apr_xml_parser_feed(parser, data, len);
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz if (status) {
f69b31136266022effeb1272d153c92a09de072djerenkrantz goto parser_error;
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz }
f69b31136266022effeb1272d153c92a09de072djerenkrantz }
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz apr_brigade_cleanup(brigade);
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz } while (!seen_eos);
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz apr_brigade_destroy(brigade);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
aa552377469071a421252dab6568c204a99cf770gstein /* tell the parser that we're done */
aa552377469071a421252dab6568c204a99cf770gstein status = apr_xml_parser_done(parser, pdoc);
f4cc246f8dd56a23d93d6e9afa8efd406b01f135gstein if (status) {
1a08a3eb0808297eb4157e30ad9dcdabe92fc4eajerenkrantz /* Some parsers are stupid and return an error on blank documents. */
1a08a3eb0808297eb4157e30ad9dcdabe92fc4eajerenkrantz if (!total_read) {
1a08a3eb0808297eb4157e30ad9dcdabe92fc4eajerenkrantz *pdoc = NULL;
1a08a3eb0808297eb4157e30ad9dcdabe92fc4eajerenkrantz return OK;
1a08a3eb0808297eb4157e30ad9dcdabe92fc4eajerenkrantz }
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00540)
f4cc246f8dd56a23d93d6e9afa8efd406b01f135gstein "XML parser error (at end). status=%d", status);
f4cc246f8dd56a23d93d6e9afa8efd406b01f135gstein return HTTP_BAD_REQUEST;
f4cc246f8dd56a23d93d6e9afa8efd406b01f135gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
c364a517c4f0db3d0a33c662c02f2d567a33e135martin#if APR_CHARSET_EBCDIC
c364a517c4f0db3d0a33c662c02f2d567a33e135martin apr_xml_parser_convert_doc(r->pool, *pdoc, ap_hdrs_from_ascii);
c364a517c4f0db3d0a33c662c02f2d567a33e135martin#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein return OK;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein parser_error:
aa552377469071a421252dab6568c204a99cf770gstein (void) apr_xml_parser_geterror(parser, errbuf, sizeof(errbuf));
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00541)
d19cb7f3aad3cca26355b1125dd10ea6fe0f330apquerna "XML Parser Error: %s", errbuf);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
aa552377469071a421252dab6568c204a99cf770gstein /* FALLTHRU */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein read_error:
aa552377469071a421252dab6568c204a99cf770gstein /* make sure the parser is terminated */
aa552377469071a421252dab6568c204a99cf770gstein (void) apr_xml_parser_done(parser, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz apr_brigade_destroy(brigade);
a4804918bbbb650c03f1954aa09a8e957589b1ccjerenkrantz
aa552377469071a421252dab6568c204a99cf770gstein /* Apache will supply a default error, plus the error log above. */
226b4a760e9b997415cf061bb3d979c0c31ae642jorton return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}