# HG changeset patch # User Daniel Atallah # Date 1181317068 0 # Node ID 2af1f8ccd396aa364c01226540783f2673e9f38b # Parent ef3f817cac9119df62ed52e093a2c25eb8268edb# Parent 612dc51499643bd7c2bc94af298870dfb127e392 merge of '03da073664bc840f76d0cec53eea61517337c5a7' and '7a42aa3364e820295fa0a820d9fc4af116bae86f' diff -r ef3f817cac91 -r 2af1f8ccd396 libpurple/protocols/bonjour/bonjour.c --- a/libpurple/protocols/bonjour/bonjour.c Fri Jun 08 12:52:35 2007 +0000 +++ b/libpurple/protocols/bonjour/bonjour.c Fri Jun 08 15:37:48 2007 +0000 @@ -267,6 +267,7 @@ bonjour_convo_closed(PurpleConnection *connection, const char *who) { PurpleBuddy *buddy = purple_find_buddy(connection->account, who); + BonjourBuddy *bb; if (buddy == NULL) { @@ -277,7 +278,9 @@ return; } - bonjour_jabber_close_conversation(((BonjourData*)(connection->proto_data))->jabber_data, buddy); + bb = buddy->proto_data; + bonjour_jabber_close_conversation(bb->conversation); + bb->conversation = NULL; } static char * @@ -320,6 +323,8 @@ static gboolean plugin_unload(PurplePlugin *plugin) { + /* These shouldn't happen here because they are allocated in _init() */ + g_free(default_firstname); g_free(default_lastname); g_free(default_hostname); diff -r ef3f817cac91 -r 2af1f8ccd396 libpurple/protocols/bonjour/buddy.c --- a/libpurple/protocols/bonjour/buddy.c Fri Jun 08 12:52:35 2007 +0000 +++ b/libpurple/protocols/bonjour/buddy.c Fri Jun 08 15:37:48 2007 +0000 @@ -178,11 +178,8 @@ g_free(buddy->node); g_free(buddy->ver); - if (buddy->conversation != NULL) - { - g_free(buddy->conversation->buddy_name); - g_free(buddy->conversation); - } + bonjour_jabber_close_conversation(buddy->conversation); + buddy->conversation = NULL; #ifdef USE_BONJOUR_APPLE if (buddy->txt_query != NULL) diff -r ef3f817cac91 -r 2af1f8ccd396 libpurple/protocols/bonjour/jabber.c --- a/libpurple/protocols/bonjour/jabber.c Fri Jun 08 12:52:35 2007 +0000 +++ b/libpurple/protocols/bonjour/jabber.c Fri Jun 08 15:37:48 2007 +0000 @@ -28,7 +28,6 @@ #endif #include #include -#include #include #include @@ -45,6 +44,11 @@ #include "bonjour.h" #include "buddy.h" +#define STREAM_END "" +/* TODO: specify version='1.0' and send stream features */ +#define DOCTYPE "\n" \ + "" + static gint _connect_to_buddy(PurpleBuddy *gb) { @@ -104,6 +108,16 @@ } #endif +static BonjourJabberConversation * +bonjour_jabber_conv_new() { + + BonjourJabberConversation *bconv = g_new0(BonjourJabberConversation, 1); + bconv->socket = -1; + bconv->watcher_id = -1; + + return bconv; +} + static const char * _font_size_ichat_to_purple(int size) { @@ -125,9 +139,9 @@ } static void -_jabber_parse_and_write_message_to_ui(char *message, PurpleConnection *connection, PurpleBuddy *gb) +_jabber_parse_and_write_message_to_ui(xmlnode *message_node, PurpleConnection *connection, PurpleBuddy *gb) { - xmlnode *message_node, *body_node, *html_node, *events_node; + xmlnode *body_node, *html_node, *events_node; char *body, *html_body = NULL; const char *ichat_balloon_color = NULL; const char *ichat_text_color = NULL; @@ -136,16 +150,9 @@ const char *font_color = NULL; gboolean composing_event = FALSE; - /* Parsing of the message */ - message_node = xmlnode_from_str(message, strlen(message)); - if (message_node == NULL) + body_node = xmlnode_get_child(message_node, "body"); + if (body_node == NULL) return; - - body_node = xmlnode_get_child(message_node, "body"); - if (body_node == NULL) { - xmlnode_free(message_node); - return; - } body = xmlnode_get_data(body_node); html_node = xmlnode_get_child(message_node, "html"); @@ -171,11 +178,8 @@ font_color = xmlnode_get_attrib(html_body_font_node, "color"); html_body = xmlnode_get_data(html_body_font_node); if (html_body == NULL) - { - gint garbage = -1; /* This is the kind of formated messages that Purple creates */ - html_body = xmlnode_to_str(html_body_font_node, &garbage); - } + html_body = xmlnode_to_str(html_body_font_node, NULL); } } } @@ -191,7 +195,6 @@ { /* The user is just typing */ /* TODO: Deal with typing notification */ - xmlnode_free(message_node); g_free(body); g_free(html_body); return; @@ -207,8 +210,9 @@ if (font_size == NULL) font_size = "3"; if (ichat_text_color == NULL) ichat_text_color = "#000000"; if (ichat_balloon_color == NULL) ichat_balloon_color = "#FFFFFF"; - body = g_strconcat("", html_body, "", NULL); + body = g_strdup_printf("%s", + font_face, font_size, ichat_text_color, ichat_balloon_color, + html_body); } /* TODO: Should we do something with "composing_event" here? */ @@ -216,22 +220,20 @@ /* Send the message to the UI */ serv_got_im(connection, gb->name, body, 0, time(NULL)); - /* Free all the strings and nodes (the attributes are freed with their nodes) */ - xmlnode_free(message_node); g_free(body); g_free(html_body); } struct _check_buddy_by_address_t { const char *address; - PurpleBuddy **gb; + PurpleBuddy **pb; BonjourJabber *bj; }; static void _check_buddy_by_address(gpointer key, gpointer value, gpointer data) { - PurpleBuddy *gb = value; + PurpleBuddy *pb = value; BonjourBuddy *bb; struct _check_buddy_by_address_t *cbba = data; @@ -240,11 +242,11 @@ * is the same as the account requesting the check then continue to determine * whether the buddies IP matches the target IP. */ - if (cbba->bj->account == gb->account) + if (cbba->bj->account == pb->account) { - bb = gb->proto_data; + bb = pb->proto_data; if ((bb != NULL) && (g_ascii_strcasecmp(bb->ip, cbba->address) == 0)) - *(cbba->gb) = gb; + *(cbba->pb) = pb; } } @@ -304,10 +306,10 @@ { char *message = NULL; gint message_length; - PurpleBuddy *gb = data; - PurpleAccount *account = gb->account; + PurpleBuddy *pb = data; + PurpleAccount *account = pb->account; PurpleConversation *conversation; - BonjourBuddy *bb = gb->proto_data; + BonjourBuddy *bb = pb->proto_data; gboolean closed_conversation = FALSE; xmlnode *message_node; @@ -343,11 +345,16 @@ } else { + char *stream_start = g_strdup_printf(DOCTYPE, purple_account_get_username(pb->account), + purple_buddy_get_name(pb)); + /* TODO: This needs to be nonblocking! */ - if (send(bb->conversation->socket, DOCTYPE, strlen(DOCTYPE), 0) == -1) + if (send(bb->conversation->socket, stream_start, strlen(stream_start), 0) == -1) purple_debug_error("bonjour", "Unable to start a conversation with %s\n", bb->name); else bb->conversation->stream_started = TRUE; + + g_free(stream_start); } } @@ -356,28 +363,26 @@ * using a magic string, but xmlnode won't play nice when just * parsing an end tag */ - if (purple_str_has_prefix(message, STREAM_END) || (closed_conversation == TRUE)) { + if (closed_conversation || purple_str_has_prefix(message, STREAM_END)) { char *closed_conv_message; /* Close the socket, clear the watcher and free memory */ - if (bb->conversation != NULL) { - close(bb->conversation->socket); - purple_input_remove(bb->conversation->watcher_id); - g_free(bb->conversation->buddy_name); - g_free(bb->conversation); - bb->conversation = NULL; - } + bonjour_jabber_close_conversation(bb->conversation); + bb->conversation = NULL; /* Inform the user that the conversation has been closed */ - conversation = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, gb->name, account); - closed_conv_message = g_strdup_printf(_("%s has closed the conversation."), gb->name); + conversation = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, pb->name, account); + closed_conv_message = g_strdup_printf(_("%s has closed the conversation."), pb->name); purple_conversation_write(conversation, NULL, closed_conv_message, PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(closed_conv_message); - } else { + } else if (message_node != NULL) { /* Parse the message to get the data and send to the ui */ - _jabber_parse_and_write_message_to_ui(message, account->gc, gb); + _jabber_parse_and_write_message_to_ui(message_node, account->gc, pb); + } else { + /* TODO: Deal with receiving only a partial message */ } + g_free(message); if (message_node != NULL) xmlnode_free(message_node); } @@ -385,7 +390,7 @@ static void _server_socket_handler(gpointer data, int server_socket, PurpleInputCondition condition) { - PurpleBuddy *gb = NULL; + PurpleBuddy *pb = NULL; struct sockaddr_in their_addr; /* connector's address information */ socklen_t sin_size = sizeof(struct sockaddr); int client_socket; @@ -407,36 +412,36 @@ address_text = inet_ntoa(their_addr.sin_addr); cbba = g_new0(struct _check_buddy_by_address_t, 1); cbba->address = address_text; - cbba->gb = &gb; + cbba->pb = &pb; cbba->bj = data; g_hash_table_foreach(bl->buddies, _check_buddy_by_address, cbba); g_free(cbba); - if (gb == NULL) + if (pb == NULL) { purple_debug_info("bonjour", "We don't like invisible buddies, this is not a superheros comic\n"); close(client_socket); return; } - bb = gb->proto_data; + bb = pb->proto_data; /* Check if the conversation has been previously started */ if (bb->conversation == NULL) { - bb->conversation = g_new(BonjourJabberConversation, 1); + bb->conversation = bonjour_jabber_conv_new(); bb->conversation->socket = client_socket; - bb->conversation->stream_started = FALSE; - bb->conversation->buddy_name = g_strdup(gb->name); - bb->conversation->message_id = 1; if (bb->conversation->stream_started == FALSE) { + char *stream_start = g_strdup_printf(DOCTYPE, purple_account_get_username(pb->account), + purple_buddy_get_name(pb)); /* Start the stream */ - send(bb->conversation->socket, DOCTYPE, strlen(DOCTYPE), 0); + send(bb->conversation->socket, stream_start, strlen(stream_start), 0); bb->conversation->stream_started = TRUE; + g_free(stream_start); } /* Open a watcher for the client socket */ bb->conversation->watcher_id = purple_input_add(client_socket, PURPLE_INPUT_READ, - _client_socket_handler, gb); + _client_socket_handler, pb); } else { close(client_socket); } @@ -517,100 +522,88 @@ int bonjour_jabber_send_message(BonjourJabber *data, const gchar *to, const gchar *body) { - xmlnode *message_node = NULL; - gchar *message = NULL; - gint message_length = -1; - xmlnode *message_body_node = NULL; - xmlnode *message_html_node = NULL; - xmlnode *message_html_body_node = NULL; - xmlnode *message_html_body_font_node = NULL; - xmlnode *message_x_node = NULL; - PurpleBuddy *gb = NULL; - BonjourBuddy *bb = NULL; - PurpleConversation *conversation = NULL; - char *message_from_ui = NULL; - char *stripped_message = NULL; - gint ret; + xmlnode *message_node, *node, *node2; + gchar *message; + PurpleBuddy *pb; + BonjourBuddy *bb; + int ret; - gb = purple_find_buddy(data->account, to); - if (gb == NULL) { + pb = purple_find_buddy(data->account, to); + if (pb == NULL) { purple_debug_info("bonjour", "Can't send a message to an offline buddy (%s).\n", to); /* You can not send a message to an offline buddy */ return -10000; } - bb = (BonjourBuddy *)gb->proto_data; + bb = pb->proto_data; /* Check if there is a previously open conversation */ if (bb->conversation == NULL) { - int socket = _connect_to_buddy(gb); + int socket = _connect_to_buddy(pb); if (socket < 0) return -10001; - bb->conversation = g_new(BonjourJabberConversation, 1); + bb->conversation = bonjour_jabber_conv_new(); bb->conversation->socket = socket; - bb->conversation->stream_started = FALSE; - bb->conversation->buddy_name = g_strdup(gb->name); bb->conversation->watcher_id = purple_input_add(bb->conversation->socket, - PURPLE_INPUT_READ, _client_socket_handler, gb); + PURPLE_INPUT_READ, _client_socket_handler, pb); } + message_node = xmlnode_new("message"); + xmlnode_set_attrib(message_node, "to", bb->name); + xmlnode_set_attrib(message_node, "from", purple_account_get_username(data->account)); + xmlnode_set_attrib(message_node, "type", "chat"); + /* Enclose the message from the UI within a "font" node */ - message_body_node = xmlnode_new("body"); - stripped_message = purple_markup_strip_html(body); - xmlnode_insert_data(message_body_node, stripped_message, strlen(stripped_message)); - g_free(stripped_message); + node = xmlnode_new_child(message_node, "body"); + message = purple_markup_strip_html(body); + xmlnode_insert_data(node, message, strlen(message)); + g_free(message); - message_from_ui = g_strconcat("", body, "", NULL); - message_html_body_font_node = xmlnode_from_str(message_from_ui, strlen(message_from_ui)); - g_free(message_from_ui); - - message_html_body_node = xmlnode_new("body"); - xmlnode_insert_child(message_html_body_node, message_html_body_font_node); + node = xmlnode_new_child(message_node, "html"); + xmlnode_set_namespace(node, "http://www.w3.org/1999/xhtml"); - message_html_node = xmlnode_new("html"); - xmlnode_set_attrib(message_html_node, "xmlns", "http://www.w3.org/1999/xhtml"); - xmlnode_insert_child(message_html_node, message_html_body_node); - - message_x_node = xmlnode_new("x"); - xmlnode_set_attrib(message_x_node, "xmlns", "jabber:x:event"); - xmlnode_insert_child(message_x_node, xmlnode_new("composing")); + node = xmlnode_new_child(node, "body"); + message = g_strdup_printf("%s", body); + node2 = xmlnode_from_str(message, strlen(message)); + g_free(message); + xmlnode_insert_child(node, node2); - message_node = xmlnode_new("message"); - xmlnode_set_attrib(message_node, "to", ((BonjourBuddy*)(gb->proto_data))->name); - xmlnode_set_attrib(message_node, "from", data->account->username); - xmlnode_set_attrib(message_node, "type", "chat"); - xmlnode_insert_child(message_node, message_body_node); - xmlnode_insert_child(message_node, message_html_node); - xmlnode_insert_child(message_node, message_x_node); + node = xmlnode_new_child(message_node, "x"); + xmlnode_set_namespace(node, "jabber:x:event"); + xmlnode_insert_child(node, xmlnode_new("composing")); - message = xmlnode_to_str(message_node, &message_length); + + message = xmlnode_to_str(message_node, NULL); xmlnode_free(message_node); /* Check if the stream for the conversation has been started */ if (bb->conversation->stream_started == FALSE) { + char *stream_start = g_strdup_printf(DOCTYPE, purple_account_get_username(pb->account), + purple_buddy_get_name(pb)); /* Start the stream */ - if (send(bb->conversation->socket, DOCTYPE, strlen(DOCTYPE), 0) == -1) + if (send(bb->conversation->socket, stream_start, strlen(stream_start), 0) == -1) { + PurpleConversation *conv; + purple_debug_error("bonjour", "Unable to start a conversation\n"); purple_debug_warning("bonjour", "send error: %s\n", strerror(errno)); - conversation = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bb->name, data->account); - purple_conversation_write(conversation, NULL, + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bb->name, data->account); + purple_conversation_write(conv, NULL, _("Unable to send the message, the conversation couldn't be started."), PURPLE_MESSAGE_SYSTEM, time(NULL)); - close(bb->conversation->socket); - purple_input_remove(bb->conversation->watcher_id); - /* Free all the data related to the conversation */ - g_free(bb->conversation->buddy_name); - g_free(bb->conversation); + bonjour_jabber_close_conversation(bb->conversation); bb->conversation = NULL; + g_free(message); + g_free(stream_start); return 0; } + g_free(stream_start); bb->conversation->stream_started = TRUE; } @@ -625,23 +618,22 @@ } void -bonjour_jabber_close_conversation(BonjourJabber *data, PurpleBuddy *gb) +bonjour_jabber_close_conversation(BonjourJabberConversation *bconv) { - BonjourBuddy *bb = (BonjourBuddy*)gb->proto_data; - - if (bb->conversation != NULL) + if (bconv != NULL) { - /* Send the end of the stream to the other end of the conversation */ - send(bb->conversation->socket, STREAM_END, strlen(STREAM_END), 0); - /* Close the socket and remove the watcher */ - close(bb->conversation->socket); - purple_input_remove(bb->conversation->watcher_id); + if (bconv->socket >= 0) { + /* Send the end of the stream to the other end of the conversation */ + if (bconv->stream_started) + send(bconv->socket, STREAM_END, strlen(STREAM_END), 0); + /* TODO: We're really supposed to wait for "" before closing the socket */ + close(bconv->socket); + } + purple_input_remove(bconv->watcher_id); /* Free all the data related to the conversation */ - g_free(bb->conversation->buddy_name); - g_free(bb->conversation); - bb->conversation = NULL; + g_free(bconv); } } @@ -657,12 +649,14 @@ /* Close all the conversation sockets and remove all the watchers after sending end streams */ if (data->account->gc != NULL) { - GSList *buddies; - GSList *l; + GSList *buddies, *l; - buddies = purple_find_buddies(data->account, data->account->username); - for (l = buddies; l; l = l->next) - bonjour_jabber_close_conversation(data, l->data); + buddies = purple_find_buddies(data->account, purple_account_get_username(data->account)); + for (l = buddies; l; l = l->next) { + BonjourBuddy *bb = ((PurpleBuddy*) l->data)->proto_data; + bonjour_jabber_close_conversation(bb->conversation); + bb->conversation = NULL; + } g_slist_free(buddies); } } diff -r ef3f817cac91 -r 2af1f8ccd396 libpurple/protocols/bonjour/jabber.h --- a/libpurple/protocols/bonjour/jabber.h Fri Jun 08 12:52:35 2007 +0000 +++ b/libpurple/protocols/bonjour/jabber.h Fri Jun 08 15:37:48 2007 +0000 @@ -28,9 +28,6 @@ #include "account.h" -#define STREAM_END "" -#define DOCTYPE "\n" - typedef struct _BonjourJabber { gint port; @@ -43,9 +40,7 @@ { gint socket; gint watcher_id; - gchar* buddy_name; gboolean stream_started; - gint message_id; } BonjourJabberConversation; /** @@ -58,7 +53,7 @@ int bonjour_jabber_send_message(BonjourJabber *data, const gchar *to, const gchar *body); -void bonjour_jabber_close_conversation(BonjourJabber *data, PurpleBuddy *gb); +void bonjour_jabber_close_conversation(BonjourJabberConversation *bconv); void bonjour_jabber_stop(BonjourJabber *data); diff -r ef3f817cac91 -r 2af1f8ccd396 libpurple/protocols/bonjour/mdns_common.c --- a/libpurple/protocols/bonjour/mdns_common.c Fri Jun 08 12:52:35 2007 +0000 +++ b/libpurple/protocols/bonjour/mdns_common.c Fri Jun 08 15:37:48 2007 +0000 @@ -162,7 +162,7 @@ #ifdef USE_BONJOUR_APPLE /* hack: for win32, we need to stop listening to the advertisement pipe too */ - purple_input_remove(data->advertisement_fd); + purple_input_remove(data->advertisement_handler); DNSServiceRefDeallocate(data->advertisement); DNSServiceRefDeallocate(data->browser); diff -r ef3f817cac91 -r 2af1f8ccd396 libpurple/protocols/bonjour/mdns_types.h --- a/libpurple/protocols/bonjour/mdns_types.h Fri Jun 08 12:52:35 2007 +0000 +++ b/libpurple/protocols/bonjour/mdns_types.h Fri Jun 08 15:37:48 2007 +0000 @@ -38,7 +38,7 @@ DNSServiceRef advertisement; DNSServiceRef browser; - int advertisement_fd; /* hack... windows bonjour is broken, so we have to have this */ + int advertisement_handler; /* hack... windows bonjour is broken, so we have to have this */ #else /* USE_BONJOUR_HOWL */ sw_discovery session; sw_discovery_oid session_id; diff -r ef3f817cac91 -r 2af1f8ccd396 libpurple/protocols/bonjour/mdns_win32.c --- a/libpurple/protocols/bonjour/mdns_win32.c Fri Jun 08 12:52:35 2007 +0000 +++ b/libpurple/protocols/bonjour/mdns_win32.c Fri Jun 08 15:37:48 2007 +0000 @@ -280,7 +280,7 @@ { /* hack: Bonjour on windows is broken. We don't care about the callback but we have to listen anyway */ gint advertisement_fd = DNSServiceRefSockFD(data->advertisement); - data->advertisement_fd = purple_input_add(advertisement_fd, PURPLE_INPUT_READ, _mdns_handle_event, data->advertisement); + data->advertisement_handler = purple_input_add(advertisement_fd, PURPLE_INPUT_READ, _mdns_handle_event, data->advertisement); } }