Mercurial > pidgin.yaz
annotate libgaim/protocols/jabber/parser.c @ 15204:f814b2df9cce
[gaim-migrate @ 17993]
Blocking on Google Talk. Our Privacy API sucks so bad that even with no prior support for blocking in Jabber, this has no interface changes. If someone wanted to implement the deprecated Jabber privacy lists API, though, that would be ok by me.
committer: Tailor Script <tailor@pidgin.im>
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Thu, 14 Dec 2006 04:56:54 +0000 |
parents | 060594ebbef9 |
children |
rev | line source |
---|---|
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" | |
15098 | 29 #include "util.h" |
14192 | 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; | |
14628
58202142e9ad
[gaim-migrate @ 17369]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14623
diff
changeset
|
44 } else if(!xmlStrcmp(element_name, (xmlChar*) "stream")) { |
14192 | 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'; | |
14436 | 51 |
14628
58202142e9ad
[gaim-migrate @ 17369]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14623
diff
changeset
|
52 if(!xmlStrcmp(attributes[i], (xmlChar*) "version") |
14192 | 53 && !strcmp(attrib, "1.0")) { |
54 js->protocol_version = JABBER_PROTO_1_0; | |
14623
86e1ebd8ee7f
[gaim-migrate @ 17352]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14476
diff
changeset
|
55 g_free(attrib); |
14628
58202142e9ad
[gaim-migrate @ 17369]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14623
diff
changeset
|
56 } else if(!xmlStrcmp(attributes[i], (xmlChar*) "id")) { |
14192 | 57 if(js->stream_id) |
58 g_free(js->stream_id); | |
14623
86e1ebd8ee7f
[gaim-migrate @ 17352]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14476
diff
changeset
|
59 js->stream_id = attrib; |
14192 | 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) | |
14628
58202142e9ad
[gaim-migrate @ 17369]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14623
diff
changeset
|
70 node = xmlnode_new_child(js->current, (const char*) element_name); |
14192 | 71 else |
14628
58202142e9ad
[gaim-migrate @ 17369]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14623
diff
changeset
|
72 node = xmlnode_new((const char*) element_name); |
58202142e9ad
[gaim-migrate @ 17369]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14623
diff
changeset
|
73 xmlnode_set_namespace(node, (const char*) namespace); |
14192 | 74 |
75 for(i=0; i < nb_attributes * 5; i+=5) { | |
15097 | 76 char *txt; |
14192 | 77 int attrib_len = attributes[i+4] - attributes[i+3]; |
78 char *attrib = g_malloc(attrib_len + 1); | |
15204 | 79 char *attrib_ns = NULL; |
80 | |
81 if (attributes[i+2]) { | |
82 attrib_ns = g_strdup(attributes[i+2]);; | |
83 } | |
84 | |
14192 | 85 memcpy(attrib, attributes[i+3], attrib_len); |
86 attrib[attrib_len] = '\0'; | |
15204 | 87 |
15097 | 88 txt = attrib; |
89 attrib = gaim_unescape_html(txt); | |
90 g_free(txt); | |
15204 | 91 xmlnode_set_attrib_with_namespace(node, (const char*) attributes[i], attrib_ns, attrib); |
14192 | 92 g_free(attrib); |
15204 | 93 g_free(attrib_ns); |
14192 | 94 } |
95 | |
96 js->current = node; | |
97 } | |
98 } | |
99 | |
100 static void | |
14436 | 101 jabber_parser_element_end_libxml(void *user_data, const xmlChar *element_name, |
14192 | 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) { | |
14628
58202142e9ad
[gaim-migrate @ 17369]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14623
diff
changeset
|
110 if(!xmlStrcmp((xmlChar*) js->current->name, element_name)) |
14192 | 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 | |
14628
58202142e9ad
[gaim-migrate @ 17369]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14623
diff
changeset
|
131 xmlnode_insert_data(js->current, (const char*) text, text_len); |
14192 | 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 { | |
14476
218a36c1c9e2
[gaim-migrate @ 17194]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14436
diff
changeset
|
172 /* This seems backwards, but it makes sense. The libxml code creates |
218a36c1c9e2
[gaim-migrate @ 17194]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14436
diff
changeset
|
173 * the parser context when you try to use it (this way, it can figure |
218a36c1c9e2
[gaim-migrate @ 17194]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14436
diff
changeset
|
174 * out the encoding at creation time. So, setting up the parser is |
218a36c1c9e2
[gaim-migrate @ 17194]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14436
diff
changeset
|
175 * just a matter of destroying any current parser. */ |
14192 | 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) { | |
14476
218a36c1c9e2
[gaim-migrate @ 17194]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14436
diff
changeset
|
187 /* libxml inconsistently starts parsing on creating the |
218a36c1c9e2
[gaim-migrate @ 17194]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14436
diff
changeset
|
188 * parser, so do a ParseChunk right afterwards to force it. */ |
14192 | 189 js->context = xmlCreatePushParserCtxt(&jabber_parser_libxml, js, buf, len, NULL); |
14638 | 190 xmlParseChunk(js->context, "", 0, 0); |
14192 | 191 } else if (xmlParseChunk(js->context, buf, len, 0) < 0) { |
192 gaim_connection_error(js->gc, _("XML Parse error")); | |
193 } | |
194 } | |
195 |