Mercurial > pidgin
comparison libpurple/protocols/jabber/iq.c @ 25648:050052891c55
Pass IQ handlers type, from, id, and the child node
As QuLogic pointed out in 8a80f271, it's pointless for the handlers to re-get
the information from the IQ stanza. Additionally, instead of string-matching
the type everywhere, pass around a JabberIqType.
Last, 'child' cannot be NULL, but 'from' may be.
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Sun, 08 Feb 2009 06:31:18 +0000 |
parents | 969c89c09ad7 |
children | c8606917787a |
comparison
equal
deleted
inserted
replaced
25647:969c89c09ad7 | 25648:050052891c55 |
---|---|
170 g_free(iq->id); | 170 g_free(iq->id); |
171 xmlnode_free(iq->node); | 171 xmlnode_free(iq->node); |
172 g_free(iq); | 172 g_free(iq); |
173 } | 173 } |
174 | 174 |
175 static void jabber_iq_last_parse(JabberStream *js, xmlnode *packet) | 175 static void jabber_iq_last_parse(JabberStream *js, const char *from, |
176 JabberIqType type, const char *id, | |
177 xmlnode *packet) | |
176 { | 178 { |
177 JabberIq *iq; | 179 JabberIq *iq; |
178 const char *type; | |
179 const char *from; | |
180 const char *id; | |
181 xmlnode *query; | 180 xmlnode *query; |
182 char *idle_time; | 181 char *idle_time; |
183 | 182 |
184 type = xmlnode_get_attrib(packet, "type"); | 183 if(type == JABBER_IQ_GET) { |
185 from = xmlnode_get_attrib(packet, "from"); | |
186 id = xmlnode_get_attrib(packet, "id"); | |
187 | |
188 if(type && !strcmp(type, "get")) { | |
189 iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "jabber:iq:last"); | 184 iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "jabber:iq:last"); |
190 jabber_iq_set_id(iq, id); | 185 jabber_iq_set_id(iq, id); |
191 xmlnode_set_attrib(iq->node, "to", from); | 186 xmlnode_set_attrib(iq->node, "to", from); |
192 | 187 |
193 query = xmlnode_get_child(iq->node, "query"); | 188 query = xmlnode_get_child(iq->node, "query"); |
198 | 193 |
199 jabber_iq_send(iq); | 194 jabber_iq_send(iq); |
200 } | 195 } |
201 } | 196 } |
202 | 197 |
203 static void jabber_iq_time_parse(JabberStream *js, xmlnode *packet) | 198 static void jabber_iq_time_parse(JabberStream *js, const char *from, |
204 { | 199 JabberIqType type, const char *id, |
205 const char *type, *from, *id, *xmlns; | 200 xmlnode *child) |
201 { | |
202 const char *xmlns; | |
206 JabberIq *iq; | 203 JabberIq *iq; |
207 xmlnode *child; | |
208 time_t now_t; | 204 time_t now_t; |
209 struct tm *now; | 205 struct tm *now; |
210 | 206 |
211 time(&now_t); | 207 time(&now_t); |
212 now = localtime(&now_t); | 208 now = localtime(&now_t); |
213 | 209 |
214 type = xmlnode_get_attrib(packet, "type"); | 210 xmlns = xmlnode_get_namespace(child); |
215 from = xmlnode_get_attrib(packet, "from"); | 211 |
216 id = xmlnode_get_attrib(packet, "id"); | 212 if(type == JABBER_IQ_GET) { |
217 | |
218 if ((child = xmlnode_get_child(packet, "query"))) { | |
219 xmlns = "jabber:iq:time"; | |
220 } else if ((child = xmlnode_get_child(packet, "time"))) { | |
221 xmlns = "urn:xmpp:time"; | |
222 } else { | |
223 purple_debug_warning("jabber", "Malformed IQ time packet\n"); | |
224 return; | |
225 } | |
226 | |
227 if(type && !strcmp(type, "get")) { | |
228 xmlnode *utc; | 213 xmlnode *utc; |
229 const char *date, *tz, *display; | 214 const char *date, *tz, *display; |
230 | 215 |
231 iq = jabber_iq_new(js, JABBER_IQ_RESULT); | 216 iq = jabber_iq_new(js, JABBER_IQ_RESULT); |
232 jabber_iq_set_id(iq, id); | 217 jabber_iq_set_id(iq, id); |
233 xmlnode_set_attrib(iq->node, "to", from); | 218 xmlnode_set_attrib(iq->node, "to", from); |
234 | 219 |
235 child = xmlnode_new_child(iq->node, child->name); | 220 child = xmlnode_new_child(iq->node, child->name); |
221 xmlnode_set_namespace(child, xmlns); | |
236 utc = xmlnode_new_child(child, "utc"); | 222 utc = xmlnode_new_child(child, "utc"); |
237 | 223 |
238 if(!strcmp("urn:xmpp:time", xmlns)) { | 224 if(!strcmp("urn:xmpp:time", xmlns)) { |
239 tz = purple_get_tzoff_str(now, TRUE); | 225 tz = purple_get_tzoff_str(now, TRUE); |
240 xmlnode_insert_data(xmlnode_new_child(child, "tzo"), tz, -1); | 226 xmlnode_insert_data(xmlnode_new_child(child, "tzo"), tz, -1); |
254 | 240 |
255 jabber_iq_send(iq); | 241 jabber_iq_send(iq); |
256 } | 242 } |
257 } | 243 } |
258 | 244 |
259 static void jabber_iq_version_parse(JabberStream *js, xmlnode *packet) | 245 static void jabber_iq_version_parse(JabberStream *js, const char *from, |
246 JabberIqType type, const char *id, | |
247 xmlnode *packet) | |
260 { | 248 { |
261 JabberIq *iq; | 249 JabberIq *iq; |
262 const char *type, *from, *id; | |
263 xmlnode *query; | 250 xmlnode *query; |
264 | 251 |
265 type = xmlnode_get_attrib(packet, "type"); | 252 if(type == JABBER_IQ_GET) { |
266 | |
267 if(type && !strcmp(type, "get")) { | |
268 GHashTable *ui_info; | 253 GHashTable *ui_info; |
269 const char *ui_name = NULL, *ui_version = NULL; | 254 const char *ui_name = NULL, *ui_version = NULL; |
270 #if 0 | 255 #if 0 |
271 char *os = NULL; | 256 char *os = NULL; |
272 if(!purple_prefs_get_bool("/plugins/prpl/jabber/hide_os")) { | 257 if(!purple_prefs_get_bool("/plugins/prpl/jabber/hide_os")) { |
275 uname(&osinfo); | 260 uname(&osinfo); |
276 os = g_strdup_printf("%s %s %s", osinfo.sysname, osinfo.release, | 261 os = g_strdup_printf("%s %s %s", osinfo.sysname, osinfo.release, |
277 osinfo.machine); | 262 osinfo.machine); |
278 } | 263 } |
279 #endif | 264 #endif |
280 from = xmlnode_get_attrib(packet, "from"); | |
281 id = xmlnode_get_attrib(packet, "id"); | |
282 | 265 |
283 iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "jabber:iq:version"); | 266 iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "jabber:iq:version"); |
284 xmlnode_set_attrib(iq->node, "to", from); | 267 xmlnode_set_attrib(iq->node, "to", from); |
285 jabber_iq_set_id(iq, id); | 268 jabber_iq_set_id(iq, id); |
286 | 269 |
322 void jabber_iq_parse(JabberStream *js, xmlnode *packet) | 305 void jabber_iq_parse(JabberStream *js, xmlnode *packet) |
323 { | 306 { |
324 JabberCallbackData *jcd; | 307 JabberCallbackData *jcd; |
325 xmlnode *child, *error, *x; | 308 xmlnode *child, *error, *x; |
326 const char *xmlns; | 309 const char *xmlns; |
327 const char *type, *id, *from; | 310 const char *iq_type, *id, *from; |
311 JabberIqType type = JABBER_IQ_NONE; | |
328 JabberIqHandler *jih; | 312 JabberIqHandler *jih; |
329 | 313 |
330 /* | 314 /* |
331 * child will be either the first tag child or NULL if there is no child. | 315 * child will be either the first tag child or NULL if there is no child. |
332 * Historically, we used just the 'query' subchild, but newer XEPs use | 316 * Historically, we used just the 'query' subchild, but newer XEPs use |
336 for (child = packet->child; child; child = child->next) { | 320 for (child = packet->child; child; child = child->next) { |
337 if (child->type == XMLNODE_TYPE_TAG) | 321 if (child->type == XMLNODE_TYPE_TAG) |
338 break; | 322 break; |
339 } | 323 } |
340 | 324 |
341 type = xmlnode_get_attrib(packet, "type"); | 325 iq_type = xmlnode_get_attrib(packet, "type"); |
342 from = xmlnode_get_attrib(packet, "from"); | 326 from = xmlnode_get_attrib(packet, "from"); |
343 id = xmlnode_get_attrib(packet, "id"); | 327 id = xmlnode_get_attrib(packet, "id"); |
344 | 328 |
345 if(type == NULL || !(!strcmp(type, "get") || !strcmp(type, "set") | 329 if (iq_type) { |
346 || !strcmp(type, "result") || !strcmp(type, "error"))) { | 330 if (!strcmp(iq_type, "get")) |
331 type = JABBER_IQ_GET; | |
332 else if (!strcmp(iq_type, "set")) | |
333 type = JABBER_IQ_SET; | |
334 else if (!strcmp(iq_type, "result")) | |
335 type = JABBER_IQ_RESULT; | |
336 else if (!strcmp(iq_type, "error")) | |
337 type = JABBER_IQ_ERROR; | |
338 } | |
339 | |
340 if (type == JABBER_IQ_NONE) { | |
347 purple_debug_error("jabber", "IQ with invalid type ('%s') - ignoring.\n", | 341 purple_debug_error("jabber", "IQ with invalid type ('%s') - ignoring.\n", |
348 type ? type : "(null)"); | 342 iq_type ? iq_type : "(null)"); |
349 return; | 343 return; |
350 } | 344 } |
351 | 345 |
352 /* All IQs must have an ID, so send an error for a set/get that doesn't */ | 346 /* All IQs must have an ID, so send an error for a set/get that doesn't */ |
353 if(!id || !*id) { | 347 if(!id || !*id) { |
354 | 348 |
355 if(!strcmp(type, "set") || !strcmp(type, "get")) { | 349 if(type == JABBER_IQ_SET || type == JABBER_IQ_GET) { |
356 JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR); | 350 JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR); |
357 | 351 |
358 xmlnode_free(iq->node); | 352 xmlnode_free(iq->node); |
359 iq->node = xmlnode_copy(packet); | 353 iq->node = xmlnode_copy(packet); |
360 xmlnode_set_attrib(iq->node, "to", from); | 354 xmlnode_set_attrib(iq->node, "to", from); |
368 x = xmlnode_new_child(error, "bad-request"); | 362 x = xmlnode_new_child(error, "bad-request"); |
369 xmlnode_set_namespace(x, "urn:ietf:params:xml:ns:xmpp-stanzas"); | 363 xmlnode_set_namespace(x, "urn:ietf:params:xml:ns:xmpp-stanzas"); |
370 | 364 |
371 jabber_iq_send(iq); | 365 jabber_iq_send(iq); |
372 } else | 366 } else |
373 purple_debug_error("jabber", "IQ of type '%s' missing id - ignoring.\n", type); | 367 purple_debug_error("jabber", "IQ of type '%s' missing id - ignoring.\n", |
368 iq_type); | |
374 | 369 |
375 return; | 370 return; |
376 } | 371 } |
377 | 372 |
378 /* First, lets see if a special callback got registered */ | 373 /* First, lets see if a special callback got registered */ |
379 if(!strcmp(type, "result") || !strcmp(type, "error")) { | 374 if(type == JABBER_IQ_RESULT || type == JABBER_IQ_ERROR) { |
380 if(id && *id && (jcd = g_hash_table_lookup(js->iq_callbacks, id))) { | 375 if(id && *id && (jcd = g_hash_table_lookup(js->iq_callbacks, id))) { |
381 jcd->callback(js, packet, jcd->data); | 376 jcd->callback(js, packet, jcd->data); |
382 jabber_iq_remove_callback_by_id(js, id); | 377 jabber_iq_remove_callback_by_id(js, id); |
383 return; | 378 return; |
384 } | 379 } |
389 JabberIqHandlerKey key; | 384 JabberIqHandlerKey key; |
390 key.node = child->name; | 385 key.node = child->name; |
391 /* xmlns isn't being modified, I promise */ | 386 /* xmlns isn't being modified, I promise */ |
392 key.xmlns = (char *)xmlns; | 387 key.xmlns = (char *)xmlns; |
393 if((jih = g_hash_table_lookup(iq_handlers, &key))) { | 388 if((jih = g_hash_table_lookup(iq_handlers, &key))) { |
394 jih(js, packet); | 389 jih(js, from, type, id, child); |
395 return; | 390 return; |
396 } | 391 } |
397 } | 392 } |
398 | 393 |
399 purple_debug_info("jabber", "jabber_iq_parse\n"); | 394 purple_debug_info("jabber", "jabber_iq_parse\n"); |
400 | 395 |
401 /* If we get here, send the default error reply mandated by XMPP-CORE */ | 396 /* If we get here, send the default error reply mandated by XMPP-CORE */ |
402 if(!strcmp(type, "set") || !strcmp(type, "get")) { | 397 if(type == JABBER_IQ_SET || type == JABBER_IQ_GET) { |
403 JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR); | 398 JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR); |
404 | 399 |
405 xmlnode_free(iq->node); | 400 xmlnode_free(iq->node); |
406 iq->node = xmlnode_copy(packet); | 401 iq->node = xmlnode_copy(packet); |
407 xmlnode_set_attrib(iq->node, "to", from); | 402 xmlnode_set_attrib(iq->node, "to", from); |