1 /*
2    XML/HTTP response handling
3    Copyright (C) 2004-2006, Joe Orton <joe@manyfish.co.uk>
4 
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public
7    License as published by the Free Software Foundation; either
8    version 2 of the License, or (at your option) any later version.
9 
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14 
15    You should have received a copy of the GNU Library General Public
16    License along with this library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18    MA 02111-1307, USA
19 
20 */
21 
22 #include "config.h"
23 
24 #include <string.h>
25 #include <stdlib.h>
26 
27 #include "ne_internal.h"
28 #include "ne_xmlreq.h"
29 #include "ne_basic.h"
30 #include "ne_string.h"
31 
32 /* Handle an XML response parse error, setting session error string
33  * and closing the connection. */
parse_error(ne_session * sess,ne_xml_parser * parser)34 static int parse_error(ne_session *sess, ne_xml_parser *parser)
35 {
36     ne_set_error(sess, _("Could not parse response: %s"),
37                  ne_xml_get_error(parser));
38     ne_close_connection(sess);
39     return NE_ERROR;
40 }
41 
ne_xml_parse_response(ne_request * req,ne_xml_parser * parser)42 int ne_xml_parse_response(ne_request *req, ne_xml_parser *parser)
43 {
44     char buf[8000];
45     ssize_t bytes;
46     int ret = 0;
47 
48     while ((bytes = ne_read_response_block(req, buf, sizeof buf)) > 0) {
49         ret = ne_xml_parse(parser, buf, bytes);
50         if (ret)
51             return parse_error(ne_get_session(req), parser);
52     }
53 
54     if (bytes == 0) {
55         /* Tell the parser that end of document was reached: */
56         if (ne_xml_parse(parser, NULL, 0) == 0)
57             return NE_OK;
58         else
59             return parse_error(ne_get_session(req), parser);
60     } else {
61         return NE_ERROR;
62     }
63 }
64 
65 /* Returns non-zero if given content-type is an XML media type,
66  * following the RFC 3023 rules. */
media_type_is_xml(const ne_content_type * ctype)67 static int media_type_is_xml(const ne_content_type *ctype)
68 {
69     size_t stlen;
70 
71     return
72         (ne_strcasecmp(ctype->type, "text") == 0
73          && ne_strcasecmp(ctype->subtype, "xml") == 0)
74         || (ne_strcasecmp(ctype->type, "application") == 0
75             && ne_strcasecmp(ctype->subtype, "xml") == 0)
76         || ((stlen = strlen(ctype->subtype)) > 4
77             && ne_strcasecmp(ctype->subtype + stlen - 4, "+xml") == 0);
78 }
79 
ne_xml_dispatch_request(ne_request * req,ne_xml_parser * parser)80 int ne_xml_dispatch_request(ne_request *req, ne_xml_parser *parser)
81 {
82     int ret;
83 
84     do {
85         int parseit = 0;
86 
87         ret = ne_begin_request(req);
88         if (ret) break;
89 
90         if (ne_get_status(req)->klass == 2) {
91             ne_content_type ctype;
92 
93             if (ne_get_content_type(req, &ctype) == 0) {
94                 parseit = media_type_is_xml(&ctype);
95                 ne_free(ctype.value);
96             }
97         }
98 
99         if (parseit)
100             ret = ne_xml_parse_response(req, parser);
101         else
102             ret = ne_discard_response(req);
103 
104         if (ret == NE_OK)
105             ret = ne_end_request(req);
106     } while (ret == NE_RETRY);
107 
108     return ret;
109 }
110 
111