util_xml.c revision c364a517c4f0db3d0a33c662c02f2d567a33e135
842ae4bd224140319ae7feec1872b93dfd491143fielding/* Copyright 2000-2004 The Apache Software Foundation
842ae4bd224140319ae7feec1872b93dfd491143fielding *
842ae4bd224140319ae7feec1872b93dfd491143fielding * Licensed under the Apache License, Version 2.0 (the "License");
842ae4bd224140319ae7feec1872b93dfd491143fielding * you may not use this file except in compliance with the License.
842ae4bd224140319ae7feec1872b93dfd491143fielding * You may obtain a copy of the License at
842ae4bd224140319ae7feec1872b93dfd491143fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * http://www.apache.org/licenses/LICENSE-2.0
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * 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.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "apr_xml.h"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "httpd.h"
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh#include "http_protocol.h"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "http_log.h"
2261031aa94be82d7e6b1b8c367afc1b282317f5ianh#include "http_core.h"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "util_charset.h"
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein#include "util_xml.h"
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein/* used for reading input blocks */
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein#define READ_BLOCKSIZE 2048
1b21d7b3d97def358b2e923655edeb16613a1c31gstein
be3223a6a18d9a3a3cf7155d5430a5d92bcddceegstein
573394373c777e1624a481160f3d02f8fb09f3ffrjungAP_DECLARE(int) ap_xml_parse_input(request_rec * r, apr_xml_doc **pdoc)
e302f38fd646764ce1a1e1c578d794aef514a9e5sf{
1b21d7b3d97def358b2e923655edeb16613a1c31gstein apr_xml_parser *parser;
1b21d7b3d97def358b2e923655edeb16613a1c31gstein apr_bucket_brigade *brigade;
1b21d7b3d97def358b2e923655edeb16613a1c31gstein int seen_eos;
1b21d7b3d97def358b2e923655edeb16613a1c31gstein apr_status_t status;
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein char errbuf[200];
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein apr_size_t total_read = 0;
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein apr_size_t limit_xml_body = ap_get_limit_xml_body(r);
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein int result = HTTP_BAD_REQUEST;
1b21d7b3d97def358b2e923655edeb16613a1c31gstein
1b21d7b3d97def358b2e923655edeb16613a1c31gstein parser = apr_xml_parser_create(r->pool);
1b21d7b3d97def358b2e923655edeb16613a1c31gstein brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
d633ae407c3c956cb2d67ff27055ff0e640967adfuankg
d633ae407c3c956cb2d67ff27055ff0e640967adfuankg seen_eos = 0;
d633ae407c3c956cb2d67ff27055ff0e640967adfuankg total_read = 0;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
b0f20a4a26bcfa85724b1c2e5ec6a077f12ef44crbb do {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_bucket *bucket;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* read the body, stuffing it into the parser */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding status = ap_get_brigade(r->input_filters, brigade,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding AP_MODE_READBYTES, APR_BLOCK_READ,
cf8fe49d9d89cfa4b62cb2b1376ca6f25b81b362trawick READ_BLOCKSIZE);
874fa3c6bbef1b4ab4bed0a2ff9852b21ea1b187trawick
56589be3d7a3e9343370df240010c6928cc78b39jkaluza if (status != APR_SUCCESS) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding goto read_error;
b08558bf6a64f9501ad3eca34eaf4d978bd928cfsf }
b08558bf6a64f9501ad3eca34eaf4d978bd928cfsf
b08558bf6a64f9501ad3eca34eaf4d978bd928cfsf for (bucket = APR_BRIGADE_FIRST(brigade);
b08558bf6a64f9501ad3eca34eaf4d978bd928cfsf bucket != APR_BRIGADE_SENTINEL(brigade);
b08558bf6a64f9501ad3eca34eaf4d978bd928cfsf bucket = APR_BUCKET_NEXT(bucket))
7184de27ec1d62a83c41cdeac0953ca9fd661e8csf {
7184de27ec1d62a83c41cdeac0953ca9fd661e8csf const char *data;
7184de27ec1d62a83c41cdeac0953ca9fd661e8csf apr_size_t len;
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (APR_BUCKET_IS_EOS(bucket)) {
963f8b44ac95132458ea3b6aaa8ebc135188e473takashi seen_eos = 1;
963f8b44ac95132458ea3b6aaa8ebc135188e473takashi break;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
a7318397b355119d990d1f311b951dea2aafc53arbb if (APR_BUCKET_IS_METADATA(bucket)) {
a7318397b355119d990d1f311b951dea2aafc53arbb continue;
ce4dc40a4e87991087488f70d96d3447d7557294sf }
a7318397b355119d990d1f311b951dea2aafc53arbb
a7318397b355119d990d1f311b951dea2aafc53arbb status = apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
cb9e6e5c78f5a1690214e9548250fc6af1fc73b5wrowe if (status != APR_SUCCESS) {
cb9e6e5c78f5a1690214e9548250fc6af1fc73b5wrowe goto read_error;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
8a3228198adb03e6996f7738c361a612777ecab6aaron
8a3228198adb03e6996f7738c361a612777ecab6aaron total_read += len;
8a3228198adb03e6996f7738c361a612777ecab6aaron if (limit_xml_body && total_read > limit_xml_body) {
8a3228198adb03e6996f7738c361a612777ecab6aaron ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
8a3228198adb03e6996f7738c361a612777ecab6aaron "XML request body is larger than the configured "
8a3228198adb03e6996f7738c361a612777ecab6aaron "limit of %lu", (unsigned long)limit_xml_body);
8a3228198adb03e6996f7738c361a612777ecab6aaron result = HTTP_REQUEST_ENTITY_TOO_LARGE;
8a3228198adb03e6996f7738c361a612777ecab6aaron goto read_error;
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf }
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf status = apr_xml_parser_feed(parser, data, len);
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf if (status) {
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf goto parser_error;
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf }
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf }
d37a236a4b64d0aeb4a8bbfd3978503af8c82765sf
8a3228198adb03e6996f7738c361a612777ecab6aaron apr_brigade_cleanup(brigade);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding } while (!seen_eos);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
649c9dd342a580016d29c2866de88a4609eb6457wrowe apr_brigade_destroy(brigade);
649c9dd342a580016d29c2866de88a4609eb6457wrowe
0f57a69cc84c59eacda1179763ae42ca88f1a577wrowe /* tell the parser that we're done */
18b197c6ba1d5b8bb5b2fb372ef752f87e56912atrawick status = apr_xml_parser_done(parser, pdoc);
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick if (status) {
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick /* Some parsers are stupid and return an error on blank documents. */
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick if (!total_read) {
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick *pdoc = NULL;
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick return OK;
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick }
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
82d2a5debc5a6ed2118ac5916d9ba36ad0b5d78btrawick "XML parser error (at end). status=%d", status);
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton return HTTP_BAD_REQUEST;
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim }
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim#if APR_CHARSET_EBCDIC
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton apr_xml_parser_convert_doc(r->pool, *pdoc, ap_hdrs_from_ascii);
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton#endif
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton return OK;
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton parser_error:
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton (void) apr_xml_parser_geterror(parser, errbuf, sizeof(errbuf));
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton "%s", errbuf);
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton /* FALLTHRU */
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton read_error:
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe /* make sure the parser is terminated */
7117ace448072813fa6eb7180ef206fc2e8fcfc7wrowe (void) apr_xml_parser_done(parser, NULL);
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton apr_brigade_destroy(brigade);
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton /* Apache will supply a default error, plus the error log above. */
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton return result;
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton}
f3a0be90718c1fa5da1bf25e38974d2db3ef8a30jorton