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