14192
|
1 /*
|
|
2 * gaim - Jabber XML parser stuff
|
|
3 *
|
|
4 * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
|
|
5 *
|
|
6 * This program is free software; you can redistribute it and/or modify
|
|
7 * it under the terms of the GNU General Public License as published by
|
|
8 * the Free Software Foundation; either version 2 of the License, or
|
|
9 * (at your option) any later version.
|
|
10 *
|
|
11 * This program is distributed in the hope that it will be useful,
|
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14 * GNU General Public License for more details.
|
|
15 *
|
|
16 * You should have received a copy of the GNU General Public License
|
|
17 * along with this program; if not, write to the Free Software
|
|
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
19 *
|
|
20 */
|
|
21 #include "internal.h"
|
|
22
|
|
23 #include <libxml/parser.h>
|
|
24
|
|
25 #include "connection.h"
|
|
26 #include "debug.h"
|
|
27 #include "jabber.h"
|
|
28 #include "parser.h"
|
|
29 #include "xmlnode.h"
|
|
30
|
|
31 static void
|
|
32 jabber_parser_element_start_libxml(void *user_data,
|
|
33 const xmlChar *element_name, const xmlChar *prefix, const xmlChar *namespace,
|
|
34 int nb_namespaces, const xmlChar **namespaces,
|
|
35 int nb_attributes, int nb_defaulted, const xmlChar **attributes)
|
|
36 {
|
|
37 JabberStream *js = user_data;
|
|
38 xmlnode *node;
|
|
39 int i;
|
|
40
|
|
41 if(!element_name) {
|
|
42 return;
|
|
43 } else if(!strcmp(element_name, "stream")) {
|
|
44 js->protocol_version = JABBER_PROTO_0_9;
|
|
45 for(i=0; i < nb_attributes * 5; i += 5) {
|
|
46 int attrib_len = attributes[i+4] - attributes[i+3];
|
|
47 char *attrib = g_malloc(attrib_len + 1);
|
|
48 memcpy(attrib, attributes[i+3], attrib_len);
|
|
49 attrib[attrib_len] = '\0';
|
14436
|
50
|
14192
|
51 if(!strcmp(attributes[i], "version")
|
|
52 && !strcmp(attrib, "1.0")) {
|
|
53 js->protocol_version = JABBER_PROTO_1_0;
|
|
54 } else if(!strcmp(attributes[i], "id")) {
|
|
55 if(js->stream_id)
|
|
56 g_free(js->stream_id);
|
|
57 js->stream_id = g_strdup(attrib);
|
|
58 }
|
|
59 g_free(attrib);
|
|
60 }
|
|
61 if(js->protocol_version == JABBER_PROTO_0_9)
|
|
62 js->auth_type = JABBER_AUTH_IQ_AUTH;
|
|
63
|
|
64 if(js->state == JABBER_STREAM_INITIALIZING)
|
|
65 jabber_stream_set_state(js, JABBER_STREAM_AUTHENTICATING);
|
|
66 } else {
|
|
67
|
|
68 if(js->current)
|
|
69 node = xmlnode_new_child(js->current, element_name);
|
|
70 else
|
|
71 node = xmlnode_new(element_name);
|
|
72 xmlnode_set_namespace(node, namespace);
|
|
73
|
|
74 for(i=0; i < nb_attributes * 5; i+=5) {
|
|
75 int attrib_len = attributes[i+4] - attributes[i+3];
|
|
76 char *attrib = g_malloc(attrib_len + 1);
|
|
77 memcpy(attrib, attributes[i+3], attrib_len);
|
|
78 attrib[attrib_len] = '\0';
|
|
79 xmlnode_set_attrib(node, attributes[i], attrib);
|
|
80 g_free(attrib);
|
|
81 }
|
|
82
|
|
83 js->current = node;
|
|
84 }
|
|
85 }
|
|
86
|
|
87 static void
|
14436
|
88 jabber_parser_element_end_libxml(void *user_data, const xmlChar *element_name,
|
14192
|
89 const xmlChar *prefix, const xmlChar *namespace)
|
|
90 {
|
|
91 JabberStream *js = user_data;
|
|
92
|
|
93 if(!js->current)
|
|
94 return;
|
|
95
|
|
96 if(js->current->parent) {
|
|
97 if(!strcmp(js->current->name, element_name))
|
|
98 js->current = js->current->parent;
|
|
99 } else {
|
|
100 xmlnode *packet = js->current;
|
|
101 js->current = NULL;
|
|
102 jabber_process_packet(js, packet);
|
|
103 xmlnode_free(packet);
|
|
104 }
|
|
105 }
|
|
106
|
|
107 static void
|
|
108 jabber_parser_element_text_libxml(void *user_data, const xmlChar *text, int text_len)
|
|
109 {
|
|
110 JabberStream *js = user_data;
|
|
111
|
|
112 if(!js->current)
|
|
113 return;
|
|
114
|
|
115 if(!text || !text_len)
|
|
116 return;
|
|
117
|
|
118 xmlnode_insert_data(js->current, text, text_len);
|
|
119 }
|
|
120
|
|
121 static xmlSAXHandler jabber_parser_libxml = {
|
|
122 .internalSubset = NULL,
|
|
123 .isStandalone = NULL,
|
|
124 .hasInternalSubset = NULL,
|
|
125 .hasExternalSubset = NULL,
|
|
126 .resolveEntity = NULL,
|
|
127 .getEntity = NULL,
|
|
128 .entityDecl = NULL,
|
|
129 .notationDecl = NULL,
|
|
130 .attributeDecl = NULL,
|
|
131 .elementDecl = NULL,
|
|
132 .unparsedEntityDecl = NULL,
|
|
133 .setDocumentLocator = NULL,
|
|
134 .startDocument = NULL,
|
|
135 .endDocument = NULL,
|
|
136 .startElement = NULL,
|
|
137 .endElement = NULL,
|
|
138 .reference = NULL,
|
|
139 .characters = jabber_parser_element_text_libxml,
|
|
140 .ignorableWhitespace = NULL,
|
|
141 .processingInstruction = NULL,
|
|
142 .comment = NULL,
|
|
143 .warning = NULL,
|
|
144 .error = NULL,
|
|
145 .fatalError = NULL,
|
|
146 .getParameterEntity = NULL,
|
|
147 .cdataBlock = NULL,
|
|
148 .externalSubset = NULL,
|
|
149 .initialized = XML_SAX2_MAGIC,
|
|
150 ._private = NULL,
|
|
151 .startElementNs = jabber_parser_element_start_libxml,
|
|
152 .endElementNs = jabber_parser_element_end_libxml,
|
|
153 .serror = NULL
|
|
154 };
|
|
155
|
|
156 void
|
|
157 jabber_parser_setup(JabberStream *js)
|
|
158 {
|
|
159 /* This seems backwards, but it makes sense. The libxml code creates the parser
|
|
160 * context when you try to use it (this way, it can figure out the encoding at
|
|
161 * creation time. So, setting up the parser is just a matter of destroying any
|
|
162 * current parser. */
|
|
163 if (js->context) {
|
|
164 xmlParseChunk(js->context, NULL,0,1);
|
|
165 xmlFreeParserCtxt(js->context);
|
|
166 js->context = NULL;
|
|
167 }
|
|
168 }
|
|
169
|
|
170
|
|
171 void jabber_parser_process(JabberStream *js, const char *buf, int len)
|
|
172 {
|
|
173 if (js->context == NULL) {
|
|
174 /* libxml inconsistently starts parsing on creating the parser, so so a ParseChunk
|
|
175 * right afterwards to force it. */
|
|
176 js->context = xmlCreatePushParserCtxt(&jabber_parser_libxml, js, buf, len, NULL);
|
|
177 } else if (xmlParseChunk(js->context, buf, len, 0) < 0) {
|
|
178 gaim_connection_error(js->gc, _("XML Parse error"));
|
|
179 }
|
|
180 }
|
|
181
|