comparison src/protocols/bonjour/jabber.c @ 13902:425e0f861e88

[gaim-migrate @ 16390] A small part of sf patch #1490646, from Jonty Wareing & Jono Cole "Fix & Enhance the Bonjour prpl" "Several instances of "magic strings" have been replaced with proper XML parsing code in the Bonjour prpl, allowing it to communicate with other Gaim clients (a misplaced space in one of the strings prevented this), and every other Bonjour chat client we can find. A fair amount of completely redundant code was also stripped, which in combination with the proper XML parsing allows the client to be far more flexible about Jabber errors in other clients." committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Sat, 01 Jul 2006 22:32:20 +0000
parents 47c3d00713af
children 8264f52a1142
comparison
equal deleted inserted replaced
13901:e40263ba9680 13902:425e0f861e88
307 GaimAccount *account = gb->account; 307 GaimAccount *account = gb->account;
308 GaimConversation *conversation; 308 GaimConversation *conversation;
309 char *closed_conv_message; 309 char *closed_conv_message;
310 BonjourBuddy *bb = (BonjourBuddy*)gb->proto_data; 310 BonjourBuddy *bb = (BonjourBuddy*)gb->proto_data;
311 gboolean closed_conversation = FALSE; 311 gboolean closed_conversation = FALSE;
312 xmlnode *message_node = NULL;
312 313
313 /* Read the data from the socket */ 314 /* Read the data from the socket */
314 if ((message_length = _read_data(socket, &message)) == -1) { 315 if ((message_length = _read_data(socket, &message)) == -1) {
315 /* There have been an error reading from the socket */ 316 /* There have been an error reading from the socket */
316 return; 317 return;
323 message[message_length - 1] = '\0'; 324 message[message_length - 1] = '\0';
324 message_length--; 325 message_length--;
325 } 326 }
326 } 327 }
327 328
328 /* Check if the start of the doctype has been received, if not check that the current */ 329 /* Parse the message into an XMLnode for analysis */
329 /* data is the doctype */ 330 message_node = xmlnode_from_str(message, strlen(message));
330 if (!(bb->conversation->start_step_one))
331 {
332 if (g_str_has_prefix(message, DOCTYPE_DECLARATION))
333 {
334 bb->conversation->start_step_one = TRUE;
335 }
336 }
337 331
338 /* Check if the start of the stream has been received, if not check that the current */ 332 /* Check if the start of the stream has been received, if not check that the current */
339 /* data is the start of the stream */ 333 /* data is the start of the stream */
340 if (!(bb->conversation->start_step_two)) 334 if (!(bb->conversation->stream_started))
341 { 335 {
342 if (g_str_has_suffix(message, STREAM_START)) { 336 /* Check if this is the start of the stream */
343 bb->conversation->start_step_two = TRUE; 337 if ((message_node != NULL) &&
344 338 g_ascii_strcasecmp(xmlnode_get_attrib(message_node, "xmlns"), "jabber:client") &&
345 /* If we haven't done it yet, we have to sent the start of the stream to the other buddy */ 339 (xmlnode_get_attrib(message_node,"xmlns:stream") != NULL))
346 if (!(bb->conversation->stream_started)) { 340 {
347 if (send(bb->conversation->socket, DOCTYPE, strlen(DOCTYPE), 0) == -1) { 341 bb->conversation->stream_started = TRUE;
348 gaim_debug_error("bonjour", "Unable to start a conversation with %s\n", bb->name); 342 }
349 } 343 else
344 {
345 /* TODO: This needs to be nonblocking! */
346 if (send(bb->conversation->socket, DOCTYPE, strlen(DOCTYPE), 0) == -1)
347 {
348 gaim_debug_error("bonjour", "Unable to start a conversation with %s\n", bb->name);
350 } 349 }
351 } 350 else
352 return; 351 {
353 } 352 bb->conversation->stream_started = TRUE;
354 353 }
355 /* Check that this is not the end of the conversation */ 354 }
355 }
356
357 /*
358 * Check that this is not the end of the conversation. This is
359 * using a magic string, but xmlnode won't play nice when just
360 * parsing an end tag
361 */
356 if (g_str_has_prefix(message, STREAM_END) || (closed_conversation == TRUE)) { 362 if (g_str_has_prefix(message, STREAM_END) || (closed_conversation == TRUE)) {
357 /* Close the socket, clear the watcher and free memory */ 363 /* Close the socket, clear the watcher and free memory */
358 if (bb->conversation != NULL) { 364 if (bb->conversation != NULL) {
359 close(bb->conversation->socket); 365 close(bb->conversation->socket);
360 gaim_input_remove(bb->conversation->watcher_id); 366 gaim_input_remove(bb->conversation->watcher_id);
370 g_free(closed_conv_message); 376 g_free(closed_conv_message);
371 } else { 377 } else {
372 /* Parse the message to get the data and send to the ui */ 378 /* Parse the message to get the data and send to the ui */
373 _jabber_parse_and_write_message_to_ui(message, account->gc, gb); 379 _jabber_parse_and_write_message_to_ui(message, account->gc, gb);
374 } 380 }
381
382 xmlnode_free(message_node);
375 } 383 }
376 384
377 static void 385 static void
378 _server_socket_handler(gpointer data, int server_socket, GaimInputCondition condition) 386 _server_socket_handler(gpointer data, int server_socket, GaimInputCondition condition)
379 { 387 {
417 /* Check if the conversation has been previously started */ 425 /* Check if the conversation has been previously started */
418 if (bb->conversation == NULL) 426 if (bb->conversation == NULL)
419 { 427 {
420 bb->conversation = g_new(BonjourJabberConversation, 1); 428 bb->conversation = g_new(BonjourJabberConversation, 1);
421 bb->conversation->socket = client_socket; 429 bb->conversation->socket = client_socket;
422 bb->conversation->start_step_one = FALSE;
423 bb->conversation->start_step_two = FALSE;
424 bb->conversation->stream_started = FALSE; 430 bb->conversation->stream_started = FALSE;
425 bb->conversation->buddy_name = g_strdup(gb->name); 431 bb->conversation->buddy_name = g_strdup(gb->name);
426 bb->conversation->message_id = 1; 432 bb->conversation->message_id = 1;
427 433
428 if (bb->conversation->stream_started == FALSE) { 434 if (bb->conversation->stream_started == FALSE) {
551 /* Check if there is a previously open conversation */ 557 /* Check if there is a previously open conversation */
552 if (bb->conversation == NULL) 558 if (bb->conversation == NULL)
553 { 559 {
554 bb->conversation = g_new(BonjourJabberConversation, 1); 560 bb->conversation = g_new(BonjourJabberConversation, 1);
555 bb->conversation->socket = _connect_to_buddy(gb); 561 bb->conversation->socket = _connect_to_buddy(gb);
556 bb->conversation->start_step_one = FALSE;
557 bb->conversation->start_step_two = FALSE;
558 bb->conversation->stream_started = FALSE; 562 bb->conversation->stream_started = FALSE;
559 bb->conversation->buddy_name = g_strdup(gb->name); 563 bb->conversation->buddy_name = g_strdup(gb->name);
560 bb->conversation->watcher_id = gaim_input_add(bb->conversation->socket, 564 bb->conversation->watcher_id = gaim_input_add(bb->conversation->socket,
561 GAIM_INPUT_READ, _client_socket_handler, gb); 565 GAIM_INPUT_READ, _client_socket_handler, gb);
562 } 566 }
563 567
564 /* Check if the stream for the conversation has been started */ 568 /* Check if the stream for the conversation has been started */
565 if (bb->conversation->stream_started == FALSE) 569 if (bb->conversation->stream_started == FALSE)
566 { 570 {