Imported Upstream version 2.5.11
[libapache-mod-security.git] / apache2 / msc_xml.c
1 /*
2  * ModSecurity for Apache 2.x, http://www.modsecurity.org/
3  * Copyright (c) 2004-2009 Breach Security, Inc. (http://www.breach.com/)
4  *
5  * This product is released under the terms of the General Public Licence,
6  * version 2 (GPLv2). Please refer to the file LICENSE (included with this
7  * distribution) which contains the complete text of the licence.
8  *
9  * There are special exceptions to the terms and conditions of the GPL
10  * as it is applied to this software. View the full text of the exception in
11  * file MODSECURITY_LICENSING_EXCEPTION in the directory of this software
12  * distribution.
13  *
14  * If any of the files related to licensing are missing or if you have any
15  * other questions related to licensing please contact Breach Security, Inc.
16  * directly using the email address support@breach.com.
17  *
18  */
19 #include "msc_xml.h"
20
21
22 /**
23  * Initialise XML parser.
24  */
25 int xml_init(modsec_rec *msr, char **error_msg) {
26     if (error_msg == NULL) return -1;
27     *error_msg = NULL;
28
29     msr->xml = apr_pcalloc(msr->mp, sizeof(xml_data));
30     if (msr->xml == NULL) return -1;
31
32     return 1;
33 }
34
35 #if 0
36 static void xml_receive_sax_error(void *data, const char *msg, ...) {
37     modsec_rec *msr = (modsec_rec *)data;
38     char message[256];
39
40     if (msr == NULL) return;
41
42     apr_snprintf(message, sizeof(message), "%s (line %d offset %d)",
43         log_escape_nq(msr->mp, msr->xml->parsing_ctx->lastError.message),
44         msr->xml->parsing_ctx->lastError.line,
45         msr->xml->parsing_ctx->lastError.int2);
46
47     msr_log(msr, 5, "XML: Parsing error: %s", message);
48 }
49 #endif
50
51 /**
52  * Feed one chunk of data to the XML parser.
53  */
54 int xml_process_chunk(modsec_rec *msr, const char *buf, unsigned int size, char **error_msg) {
55     if (error_msg == NULL) return -1;
56     *error_msg = NULL;
57
58     /* We want to initialise our parsing context here, to
59      * enable us to pass it the first chunk of data so that
60      * it can attempt to auto-detect the encoding.
61      */
62     if (msr->xml->parsing_ctx == NULL) {
63
64         /* First invocation. */
65
66         msr_log(msr, 4, "XML: Initialising parser.");
67
68         /* NOTE When Sax interface is used libxml will not
69          *      create the document object, but we need it.
70
71         msr->xml->sax_handler = (xmlSAXHandler *)apr_pcalloc(msr->mp, sizeof(xmlSAXHandler));
72         if (msr->xml->sax_handler == NULL) return -1;
73         msr->xml->sax_handler->error = xml_receive_sax_error;
74         msr->xml->sax_handler->warning = xml_receive_sax_error;
75         msr->xml->parsing_ctx = xmlCreatePushParserCtxt(msr->xml->sax_handler, msr,
76             buf, size, "body.xml");
77
78         */
79
80         msr->xml->parsing_ctx = xmlCreatePushParserCtxt(NULL, NULL, buf, size, "body.xml");
81         if (msr->xml->parsing_ctx == NULL) {
82             *error_msg = apr_psprintf(msr->mp, "XML: Failed to create parsing context.");
83             return -1;
84         }
85     } else {
86
87         /* Not a first invocation. */
88
89         xmlParseChunk(msr->xml->parsing_ctx, buf, size, 0);
90         if (msr->xml->parsing_ctx->wellFormed != 1) {
91             *error_msg = apr_psprintf(msr->mp, "XML: Failed parsing document.");
92             return -1;
93         }
94     }
95
96     return 1;
97 }
98
99 /**
100  * Finalise XML parsing.
101  */
102 int xml_complete(modsec_rec *msr, char **error_msg) {
103     if (error_msg == NULL) return -1;
104     *error_msg = NULL;
105
106     /* Only if we have a context, meaning we've done some work. */
107     if (msr->xml->parsing_ctx != NULL) {
108         /* This is how we signalise the end of parsing to libxml. */
109         xmlParseChunk(msr->xml->parsing_ctx, NULL, 0, 1);
110
111         /* Preserve the results for our reference. */
112         msr->xml->well_formed = msr->xml->parsing_ctx->wellFormed;
113         msr->xml->doc = msr->xml->parsing_ctx->myDoc;
114
115         /* Clean up everything else. */
116         xmlFreeParserCtxt(msr->xml->parsing_ctx);
117         msr->xml->parsing_ctx = NULL;
118         msr_log(msr, 4, "XML: Parsing complete (well_formed %u).", msr->xml->well_formed);
119
120         if (msr->xml->well_formed != 1) {
121             *error_msg = apr_psprintf(msr->mp, "XML: Failed parsing document.");
122             return -1;
123         }
124     }
125
126     return 1;
127 }
128
129 /**
130  * Frees the resources used for XML parsing.
131  */
132 apr_status_t xml_cleanup(modsec_rec *msr) {
133     if (msr->xml->doc != NULL) {
134         xmlFreeDoc(msr->xml->doc);
135         msr->xml->doc = NULL;
136     }
137
138     return 1;
139 }