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);