comparison libpurple/protocols/jabber/parser.c @ 15373:5fe8042783c1

Rename gtk/ and libgaim/ to pidgin/ and libpurple/
author Sean Egan <seanegan@gmail.com>
date Sat, 20 Jan 2007 02:32:10 +0000
parents
children 0d4890637238
comparison
equal deleted inserted replaced
15372:f79e0f4df793 15373:5fe8042783c1
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 "util.h"
30 #include "xmlnode.h"
31
32 static void
33 jabber_parser_element_start_libxml(void *user_data,
34 const xmlChar *element_name, const xmlChar *prefix, const xmlChar *namespace,
35 int nb_namespaces, const xmlChar **namespaces,
36 int nb_attributes, int nb_defaulted, const xmlChar **attributes)
37 {
38 JabberStream *js = user_data;
39 xmlnode *node;
40 int i;
41
42 if(!element_name) {
43 return;
44 } else if(!xmlStrcmp(element_name, (xmlChar*) "stream")) {
45 js->protocol_version = JABBER_PROTO_0_9;
46 for(i=0; i < nb_attributes * 5; i += 5) {
47 int attrib_len = attributes[i+4] - attributes[i+3];
48 char *attrib = g_malloc(attrib_len + 1);
49 memcpy(attrib, attributes[i+3], attrib_len);
50 attrib[attrib_len] = '\0';
51
52 if(!xmlStrcmp(attributes[i], (xmlChar*) "version")
53 && !strcmp(attrib, "1.0")) {
54 js->protocol_version = JABBER_PROTO_1_0;
55 g_free(attrib);
56 } else if(!xmlStrcmp(attributes[i], (xmlChar*) "id")) {
57 if(js->stream_id)
58 g_free(js->stream_id);
59 js->stream_id = attrib;
60 }
61 }
62 if(js->protocol_version == JABBER_PROTO_0_9)
63 js->auth_type = JABBER_AUTH_IQ_AUTH;
64
65 if(js->state == JABBER_STREAM_INITIALIZING)
66 jabber_stream_set_state(js, JABBER_STREAM_AUTHENTICATING);
67 } else {
68
69 if(js->current)
70 node = xmlnode_new_child(js->current, (const char*) element_name);
71 else
72 node = xmlnode_new((const char*) element_name);
73 xmlnode_set_namespace(node, (const char*) namespace);
74
75 for(i=0; i < nb_attributes * 5; i+=5) {
76 char *txt;
77 int attrib_len = attributes[i+4] - attributes[i+3];
78 char *attrib = g_malloc(attrib_len + 1);
79 char *attrib_ns = NULL;
80
81 if (attributes[i+2]) {
82 attrib_ns = g_strdup(attributes[i+2]);;
83 }
84
85 memcpy(attrib, attributes[i+3], attrib_len);
86 attrib[attrib_len] = '\0';
87
88 txt = attrib;
89 attrib = gaim_unescape_html(txt);
90 g_free(txt);
91 xmlnode_set_attrib_with_namespace(node, (const char*) attributes[i], attrib_ns, attrib);
92 g_free(attrib);
93 g_free(attrib_ns);
94 }
95
96 js->current = node;
97 }
98 }
99
100 static void
101 jabber_parser_element_end_libxml(void *user_data, const xmlChar *element_name,
102 const xmlChar *prefix, const xmlChar *namespace)
103 {
104 JabberStream *js = user_data;
105
106 if(!js->current)
107 return;
108
109 if(js->current->parent) {
110 if(!xmlStrcmp((xmlChar*) js->current->name, element_name))
111 js->current = js->current->parent;
112 } else {
113 xmlnode *packet = js->current;
114 js->current = NULL;
115 jabber_process_packet(js, packet);
116 xmlnode_free(packet);
117 }
118 }
119
120 static void
121 jabber_parser_element_text_libxml(void *user_data, const xmlChar *text, int text_len)
122 {
123 JabberStream *js = user_data;
124
125 if(!js->current)
126 return;
127
128 if(!text || !text_len)
129 return;
130
131 xmlnode_insert_data(js->current, (const char*) text, text_len);
132 }
133
134 static xmlSAXHandler jabber_parser_libxml = {
135 .internalSubset = NULL,
136 .isStandalone = NULL,
137 .hasInternalSubset = NULL,
138 .hasExternalSubset = NULL,
139 .resolveEntity = NULL,
140 .getEntity = NULL,
141 .entityDecl = NULL,
142 .notationDecl = NULL,
143 .attributeDecl = NULL,
144 .elementDecl = NULL,
145 .unparsedEntityDecl = NULL,
146 .setDocumentLocator = NULL,
147 .startDocument = NULL,
148 .endDocument = NULL,
149 .startElement = NULL,
150 .endElement = NULL,
151 .reference = NULL,
152 .characters = jabber_parser_element_text_libxml,
153 .ignorableWhitespace = NULL,
154 .processingInstruction = NULL,
155 .comment = NULL,
156 .warning = NULL,
157 .error = NULL,
158 .fatalError = NULL,
159 .getParameterEntity = NULL,
160 .cdataBlock = NULL,
161 .externalSubset = NULL,
162 .initialized = XML_SAX2_MAGIC,
163 ._private = NULL,
164 .startElementNs = jabber_parser_element_start_libxml,
165 .endElementNs = jabber_parser_element_end_libxml,
166 .serror = NULL
167 };
168
169 void
170 jabber_parser_setup(JabberStream *js)
171 {
172 /* This seems backwards, but it makes sense. The libxml code creates
173 * the parser context when you try to use it (this way, it can figure
174 * out the encoding at creation time. So, setting up the parser is
175 * just a matter of destroying any current parser. */
176 if (js->context) {
177 xmlParseChunk(js->context, NULL,0,1);
178 xmlFreeParserCtxt(js->context);
179 js->context = NULL;
180 }
181 }
182
183
184 void jabber_parser_process(JabberStream *js, const char *buf, int len)
185 {
186 if (js->context == NULL) {
187 /* libxml inconsistently starts parsing on creating the
188 * parser, so do a ParseChunk right afterwards to force it. */
189 js->context = xmlCreatePushParserCtxt(&jabber_parser_libxml, js, buf, len, NULL);
190 xmlParseChunk(js->context, "", 0, 0);
191 } else if (xmlParseChunk(js->context, buf, len, 0) < 0) {
192 gaim_connection_error(js->gc, _("XML Parse error"));
193 }
194 }
195