Mercurial > pidgin
changeset 22102:e6e018d0bf03
merge of '464169ffadabb173b3052074b132f38025b2e88d'
and '88dc67220e1d61e540c931b9f27f5b4419809137'
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Mon, 14 Jan 2008 04:09:03 +0000 |
parents | 0b823f16162c (diff) 7ec5b5724a05 (current diff) |
children | 1439274f0852 |
files | pidgin/gtkprefs.c pidgin/gtkstatusbox.c |
diffstat | 35 files changed, 1471 insertions(+), 396 deletions(-) [+] |
line wrap: on
line diff
--- a/COPYRIGHT Mon Jan 14 04:04:08 2008 +0000 +++ b/COPYRIGHT Mon Jan 14 04:09:03 2008 +0000 @@ -322,6 +322,7 @@ Jean-Francois Roy Peter Ruibal Sam S. +Thanumalayan S. Pradyumna Sampath Arvind Samptur Tom Samstag @@ -426,6 +427,7 @@ Andrew Whewell Simon Wilkinson Dan Willemsen +Justin Williams (Jaywalker) Jason Willis Matt Wilson Dan Winship
--- a/ChangeLog Mon Jan 14 04:04:08 2008 +0000 +++ b/ChangeLog Mon Jan 14 04:09:03 2008 +0000 @@ -9,6 +9,7 @@ now required to use Bonjour. * Partial support for viewing ICQ status notes (Collin from ComBOTS GmbH). + * Support for Yahoo Messenger 7.0+ file transfer method (Thanumalayan S.) Pidgin: * Added the ability to theme conversation name colors (red and blue) @@ -22,14 +23,14 @@ Finch: * Color is used in the buddylist to indicate status, and the conversation window to indicate various message attributes. Look at the sample gntrc - file in the man-page for details. + file in the man page for details. * The default keybinding for dump-screen is now M-D and uses a file request dialog. M-d will properly delete-forward-word, and M-f has been fixed to imitate readline's behavior. * New bindings alt+tab and alt+shift+tab to help navigating between the - higlighted windows (details on the man-page). + higlighted windows (details on the man page). * Recently signed on (or off) buddies blink in the buddy list. - * New action 'Room List' in the action-list can be used to get the list of + * New action 'Room List' in the action list can be used to get the list of available chat rooms for an online account. version 2.3.1 (12/7/2007):
--- a/ChangeLog.API Mon Jan 14 04:04:08 2008 +0000 +++ b/ChangeLog.API Mon Jan 14 04:09:03 2008 +0000 @@ -18,6 +18,18 @@ * purple_roomlist_field_get_type * purple_roomlist_field_get_label * purple_roomlist_field_get_hidden + * unlocalized_name field in PurpleAttentionType for UIs that need it. + * Some accessor and mutator functions for PurpleAttentionType: + * purple_attention_type_set_name + * purple_attention_type_set_incoming_desc + * purple_attention_type_set_outgoing_desc + * purple_attention_type_set_icon_name + * purple_attention_type_set_unlocalized_name + * purple_attention_type_get_name + * purple_attention_type_get_incoming_desc + * purple_attention_type_get_outgoing_desc + * purple_attention_type_get_icon_name + * purple_attention_type_get_unlocalized_name Pidgin: Added:
--- a/finch/gntroomlist.c Mon Jan 14 04:04:08 2008 +0000 +++ b/finch/gntroomlist.c Mon Jan 14 04:09:03 2008 +0000 @@ -287,10 +287,10 @@ froomlist.accounts = accounts = gnt_combo_box_new(); reset_account_list(account); - gnt_box_add_widget(GNT_BOX(window), froomlist.accounts); - g_signal_connect(G_OBJECT(froomlist.accounts), "selection-changed", + gnt_box_add_widget(GNT_BOX(window), accounts); + g_signal_connect(G_OBJECT(accounts), "selection-changed", G_CALLBACK(roomlist_account_changed), NULL); - froomlist.account = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(froomlist.accounts)); + froomlist.account = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(accounts)); froomlist.tree = tree = gnt_tree_new_with_columns(2); gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
--- a/libpurple/dbus-server.c Mon Jan 14 04:04:08 2008 +0000 +++ b/libpurple/dbus-server.c Mon Jan 14 04:09:03 2008 +0000 @@ -689,6 +689,7 @@ switch (purple_values[i]->type) { case PURPLE_TYPE_INT: + case PURPLE_TYPE_ENUM: xint = my_arg(gint); dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &xint); break;
--- a/libpurple/protocols/jabber/jabber.c Mon Jan 14 04:04:08 2008 +0000 +++ b/libpurple/protocols/jabber/jabber.c Mon Jan 14 04:09:03 2008 +0000 @@ -2301,14 +2301,10 @@ GList *jabber_attention_types(PurpleAccount *account) { static GList *types = NULL; - PurpleAttentionType *attn; if (!types) { - attn = g_new0(PurpleAttentionType, 1); - attn->name = _("Buzz"); - attn->incoming_description = _("%s has buzzed you!"); - attn->outgoing_description = _("Buzzing %s..."); - types = g_list_append(types, attn); + types = g_list_append(types, purple_attention_type_new("Buzz", _("Buzz"), + _("%s has buzzed you!"), _("Buzzing %s..."))); } return types;
--- a/libpurple/protocols/msn/msn.c Mon Jan 14 04:04:08 2008 +0000 +++ b/libpurple/protocols/msn/msn.c Mon Jan 14 04:09:03 2008 +0000 @@ -126,11 +126,8 @@ static GList *list = NULL; if (!list) { - attn = g_new0(PurpleAttentionType, 1); - attn->name = _("Nudge"); - attn->incoming_description = _("%s has nudged you!"); - attn->outgoing_description = _("Nudging %s..."); - list = g_list_append(list, attn); + list = g_list_append(list, purple_attention_type_new("Nudge", _("Nudge"), + _("%s has nudged you!"), _("Nudging %s..."))); } return list;
--- a/libpurple/protocols/msnp9/msn.c Mon Jan 14 04:04:08 2008 +0000 +++ b/libpurple/protocols/msnp9/msn.c Mon Jan 14 04:09:03 2008 +0000 @@ -122,15 +122,11 @@ static GList * msn_attention_types(PurpleAccount *account) { - PurpleAttentionType *attn; static GList *list = NULL; if (!list) { - attn = g_new0(PurpleAttentionType, 1); - attn->name = _("Nudge"); - attn->incoming_description = _("%s has nudged you!"); - attn->outgoing_description = _("Nudging %s..."); - list = g_list_append(list, attn); + list = g_list_append(list, purple_attention_type_new("Nudge", _("Nudge"), + _("%s has nudged you!"), _("Nudging %s..."))); } return list;
--- a/libpurple/protocols/myspace/myspace.c Mon Jan 14 04:04:08 2008 +0000 +++ b/libpurple/protocols/myspace/myspace.c Mon Jan 14 04:09:03 2008 +0000 @@ -2316,6 +2316,69 @@ msim_msg_free(blocklist_msg); } +/** + * Borrowed this code from oscar_normalize. Added checking for "if userid, get name before normalizing" + * + * Basically... Returns a string that has been formated with all the spaces and caps removed. + */ +const char *msim_normalize(const PurpleAccount *account, const char *str) { + static char normalized[BUF_LEN]; + MsimSession *session; + char *tmp1, *tmp2; + int i, j; + guint id; + + g_return_val_if_fail(str != NULL, NULL); + + if (msim_is_userid(str)) { + /* Have user ID, we need to get their username first :) */ + const char *username; + + /* If the account does not exist, we can't look up the user. */ + g_return_val_if_fail(account != NULL, str); + g_return_val_if_fail(account->gc != NULL, str); + g_return_val_if_fail(account->gc->state == PURPLE_CONNECTED, str); + + purple_debug_info("msim_normalize", "%s is a userid\n",str); + + session = (MsimSession *)account->gc->proto_data; + id = atol(str); + username = msim_uid2username_from_blist(session, id); + if (!username) { + /* Not in buddy list... scheisse... TODO: Manual Lookup! */ + /* Note: manual lookup using msim_lookup_user() is a problem inside + * msim_normalize(), because msim_lookup_user() calls a callback function + * when the user information has been looked up, but msim_normalize() expects + * the result immediately. */ + purple_debug_info("msim_normalize", "Failure! %s is not in my list\n", str); + strncpy(normalized, str, BUF_LEN); + } else { + purple_debug_info("msim_normalize","%d is %s\n", id, username); + strncpy(normalized, username, BUF_LEN); + } + } else { + /* Have username. */ + strncpy(normalized, str, BUF_LEN); + } + + /* Strip spaces. */ + for (i=0, j=0; normalized[j]; i++, j++) { + while (normalized[j] == ' ') + j++; + normalized[i] = normalized[j]; + } + normalized[i] = '\0'; + + /* Lowercase and perform UTF-8 normalization. */ + tmp1 = g_utf8_strdown(normalized, -1); + tmp2 = g_utf8_normalize(tmp1, -1, G_NORMALIZE_DEFAULT); + g_snprintf(normalized, sizeof(normalized), "%s", tmp2); + g_free(tmp2); + g_free(tmp1); + + return normalized; +} + /** Return whether the buddy can be messaged while offline. * * The protocol supports offline messages in just the same way as online @@ -2970,7 +3033,7 @@ NULL, /* rename_group */ NULL, /* buddy_free */ NULL, /* convo_closed */ - NULL, /* normalize */ + msim_normalize, /* normalize */ NULL, /* set_buddy_icon */ NULL, /* remove_group */ NULL, /* get_cb_real_name */
--- a/libpurple/protocols/myspace/myspace.h Mon Jan 14 04:04:08 2008 +0000 +++ b/libpurple/protocols/myspace/myspace.h Mon Jan 14 04:09:03 2008 +0000 @@ -180,8 +180,6 @@ #define MSIM_CONTACT_LIST_IMPORT_ALL_FRIENDS 1 #define MSIM_CONTACT_LIST_IMPORT_TOP_FRIENDS 2 -#define MsimAttentionType PurpleAttentionType - /* Functions */ gboolean msim_load(PurplePlugin *plugin); GList *msim_status_types(PurpleAccount *acct); @@ -201,6 +199,8 @@ void msim_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group); void msim_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group); +const char *msim_normalize(const PurpleAccount *account, const char *str); + gboolean msim_offline_message(const PurpleBuddy *buddy); void msim_close(PurpleConnection *gc);
--- a/libpurple/protocols/myspace/zap.c Mon Jan 14 04:04:08 2008 +0000 +++ b/libpurple/protocols/myspace/zap.c Mon Jan 14 04:09:03 2008 +0000 @@ -29,15 +29,12 @@ msim_attention_types(PurpleAccount *acct) { static GList *types = NULL; - MsimAttentionType* attn; + PurpleAttentionType* attn; if (!types) { -#define _MSIM_ADD_NEW_ATTENTION(icn, nme, incoming, outgoing) \ - attn = g_new0(MsimAttentionType, 1); \ - attn->icon_name = icn; \ - attn->name = nme; \ - attn->incoming_description = incoming; \ - attn->outgoing_description = outgoing; \ +#define _MSIM_ADD_NEW_ATTENTION(icn, ulname, nme, incoming, outgoing) \ + attn = purple_attention_type_new(ulname, nme, incoming, outgoing); \ + purple_attention_type_set_icon_name(attn, icn); \ types = g_list_append(types, attn); /* TODO: icons for each zap */ @@ -48,37 +45,46 @@ * projectile or weapon." This term often has an electrical * connotation, for example, "he was zapped by electricity when * he put a fork in the toaster." */ - _MSIM_ADD_NEW_ATTENTION(NULL, _("Zap"), _("%s has zapped you!"), _("Zapping %s...")); + _MSIM_ADD_NEW_ATTENTION(NULL, "Zap", _("Zap"), _("%s has zapped you!"), + _("Zapping %s...")); /* Whack means "to hit or strike someone with a sharp blow" */ - _MSIM_ADD_NEW_ATTENTION(NULL, _("Whack"), _("%s has whacked you!"), _("Whacking %s...")); + _MSIM_ADD_NEW_ATTENTION(NULL, "Whack", _("Whack"), + _("%s has whacked you!"), _("Whacking %s...")); /* Torch means "to set on fire." Don't worry, this doesn't * make a whole lot of sense in English, either. Feel free * to translate it literally. */ - _MSIM_ADD_NEW_ATTENTION(NULL, _("Torch"), _("%s has torched you!"), _("Torching %s...")); + _MSIM_ADD_NEW_ATTENTION(NULL, "Torch", _("Torch"), + _("%s has torched you!"), _("Torching %s...")); /* Smooch means "to kiss someone, often enthusiastically" */ - _MSIM_ADD_NEW_ATTENTION(NULL, _("Smooch"), _("%s has smooched you!"), _("Smooching %s...")); + _MSIM_ADD_NEW_ATTENTION(NULL, "Smooch", _("Smooch"), + _("%s has smooched you!"), _("Smooching %s...")); /* A hug is a display of affection; wrapping your arms around someone */ - _MSIM_ADD_NEW_ATTENTION(NULL, _("Hug"), _("%s has hugged you!"), _("Hugging %s...")); + _MSIM_ADD_NEW_ATTENTION(NULL, "Hug", _("Hug"), _("%s has hugged you!"), + _("Hugging %s...")); /* Slap means "to hit someone with an open/flat hand" */ - _MSIM_ADD_NEW_ATTENTION(NULL, _("Slap"), _("%s has slapped you!"), _("Slapping %s...")); + _MSIM_ADD_NEW_ATTENTION(NULL, "Slap", _("Slap"), + _("%s has slapped you!"), _("Slapping %s...")); /* Goose means "to pinch someone on their butt" */ - _MSIM_ADD_NEW_ATTENTION(NULL, _("Goose"), _("%s has goosed you!"), _("Goosing %s...")); + _MSIM_ADD_NEW_ATTENTION(NULL, "Goose", _("Goose"), + _("%s has goosed you!"), _("Goosing %s...")); /* A high-five is when two people's hands slap each other * in the air above their heads. It is done to celebrate * something, often a victory, or to congratulate someone. */ - _MSIM_ADD_NEW_ATTENTION(NULL, _("High-five"), _("%s has high-fived you!"), _("High-fiving %s...")); + _MSIM_ADD_NEW_ATTENTION(NULL, "High-five", _("High-five"), + _("%s has high-fived you!"), _("High-fiving %s...")); /* We're not entirely sure what the MySpace people mean by * this... but we think it's the equivalent of "prank." Or, for * someone to perform a mischievous trick or practical joke. */ - _MSIM_ADD_NEW_ATTENTION(NULL, _("Punk"), _("%s has punk'd you!"), _("Punking %s...")); + _MSIM_ADD_NEW_ATTENTION(NULL, "Punk", _("Punk"), + _("%s has punk'd you!"), _("Punking %s...")); /* Raspberry is a slang term for the vibrating sound made * when you stick your tongue out of your mouth with your @@ -87,7 +93,8 @@ * gesture, so it does not carry a harsh negative * connotation. It is generally used in a playful tone * with friends. */ - _MSIM_ADD_NEW_ATTENTION(NULL, _("Raspberry"), _("%s has raspberried you!"), _("Raspberrying %s...")); + _MSIM_ADD_NEW_ATTENTION(NULL, "Raspberry", _("Raspberry"), + _("%s has raspberried you!"), _("Raspberrying %s...")); } return types; @@ -99,14 +106,14 @@ { GList *types; MsimSession *session; - MsimAttentionType *attn; + PurpleAttentionType *attn; PurpleBuddy *buddy; session = (MsimSession *)gc->proto_data; /* Look for this attention type, by the code index given. */ types = msim_attention_types(gc->account); - attn = (MsimAttentionType *)g_list_nth_data(types, code); + attn = (PurpleAttentionType *)g_list_nth_data(types, code); if (!attn) { purple_debug_info("msim_send_attention", "got invalid zap code %d\n", code); @@ -200,12 +207,12 @@ i = 0; do { - MsimAttentionType *attn; + PurpleAttentionType *attn; - attn = (MsimAttentionType *)types->data; + attn = (PurpleAttentionType *)types->data; - act = purple_menu_action_new(attn->name, PURPLE_CALLBACK(msim_send_zap_from_menu), - GUINT_TO_POINTER(i), NULL); + act = purple_menu_action_new(purple_attention_type_get_name(attn), + PURPLE_CALLBACK(msim_send_zap_from_menu), GUINT_TO_POINTER(i), NULL); zap_menu = g_list_append(zap_menu, act); ++i;
--- a/libpurple/protocols/yahoo/util.c Mon Jan 14 04:04:08 2008 +0000 +++ b/libpurple/protocols/yahoo/util.c Mon Jan 14 04:09:03 2008 +0000 @@ -31,6 +31,70 @@ #include "yahoo.h" #include <string.h> +/* + * Returns cookies formatted as a null terminated string for the given connection. + * Must g_free return value. + * + * TODO:will work, but must test for strict correctness + */ +gchar* yahoo_get_cookies(PurpleConnection *gc) +{ + gchar *ans = NULL; + gchar *cur; + char firstflag = 1; + gchar *t1,*t2,*t3; + GSList *tmp; + GSList *cookies; + cookies = ((struct yahoo_data*)(gc->proto_data))->cookies; + tmp = cookies; + while(tmp) + { + cur = tmp->data; + t1 = ans; + t2 = g_strrstr(cur, ";expires="); + if(t2 == NULL) + t2 = g_strrstr(cur, "; expires="); + if(t2 == NULL) + { + if(firstflag) + ans = g_strdup_printf("%c=%s", cur[0], cur+2); + else + ans = g_strdup_printf("%s; %c=%s", t1, cur[0], cur+2); + } + else + { + t3 = strstr(t2+1, ";"); + if(t3 != NULL) + { + t2[0] = '\0'; + + if(firstflag) + ans = g_strdup_printf("%c=%s%s", cur[0], cur+2, t3); + else + ans = g_strdup_printf("%s; %c=%s%s", t1, cur[0], cur+2, t3); + + t2[0] = ';'; + } + else + { + t2[0] = '\0'; + + if(firstflag) + ans = g_strdup_printf("%c=%s", cur[0], cur+2); + else + ans = g_strdup_printf("%s; %c=%s", t1, cur[0], cur+2); + + t2[0] = ';'; + } + } + if(firstflag) + firstflag = 0; + else + g_free(t1); + tmp = g_slist_next(tmp); + } + return ans; +} /** * Encode some text to send to the yahoo server.
--- a/libpurple/protocols/yahoo/yahoo.c Mon Jan 14 04:04:08 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo.c Mon Jan 14 04:09:03 2008 +0000 @@ -392,6 +392,10 @@ case 97: /* Unicode status message */ unicode = !strcmp(pair->value, "1"); break; + case 244: /* client version number. Yahoo Client Detection */ + if(f && strtol(pair->value, NULL, 10)) + f->version_id = strtol(pair->value, NULL, 10); + break; default: purple_debug(PURPLE_DEBUG_ERROR, "yahoo", @@ -493,16 +497,16 @@ static void yahoo_process_cookie(struct yahoo_data *yd, char *c) { if (c[0] == 'Y') { - g_free(yd->cookie_y); + if (yd->cookie_y) + g_free(yd->cookie_y); yd->cookie_y = _getcookie(c); } else if (c[0] == 'T') { - g_free(yd->cookie_t); + if (yd->cookie_t) + g_free(yd->cookie_t); yd->cookie_t = _getcookie(c); - } else if (c[0] == 'C') { - g_free(yd->cookie_c); - yd->cookie_c = _getcookie(c); } else - purple_debug_info("yahoo", "Ignoring unrecognized cookie '%c'\n", c[0]); + purple_debug_info("yahoo", "Unrecognized cookie '%c'\n", c[0]); + yd->cookies = g_slist_prepend(yd->cookies, g_strdup(c)); } static void yahoo_process_list_15(PurpleConnection *gc, struct yahoo_packet *pkt) @@ -510,6 +514,7 @@ GSList *l = pkt->hash; PurpleAccount *account = purple_connection_get_account(gc); + struct yahoo_data *yd = gc->proto_data; GHashTable *ht; char *grp = NULL; char *norm_bud = NULL; @@ -575,6 +580,9 @@ purple_debug_info("yahoo", "Setting protocol to %d\n", f->protocol); } break; + case 59: /* somebody told cookies come here too, but im not sure */ + yahoo_process_cookie(yd, pair->value); + break; case 317: /* Stealth Setting */ if (f && (strtol(pair->value, NULL, 10) == 2)) { f->presence = YAHOO_PRESENCE_PERM_OFFLINE; @@ -1507,7 +1515,13 @@ to_y64(result96, digest, 16); pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, YAHOO_STATUS_AVAILABLE, 0); - yahoo_packet_hash(pack, "ssss", 0, name, 6, result6, 96, result96, 1, name); + yahoo_packet_hash(pack, "ssssss", + 0, name, + 6, result6, + 96, result96, + 1, name, + 244, YAHOO_CLIENT_VERSION_ID, + 135, YAHOO_CLIENT_VERSION); yahoo_packet_send_and_free(pack, yd); g_free(hash_string_p); @@ -1526,11 +1540,11 @@ char *enc_pass; struct yahoo_data *yd = gc->proto_data; - PurpleCipher *md5_cipher; + PurpleCipher *md5_cipher; PurpleCipherContext *md5_ctx; guchar md5_digest[16]; - PurpleCipher *sha1_cipher; + PurpleCipher *sha1_cipher; PurpleCipherContext *sha1_ctx1; PurpleCipherContext *sha1_ctx2; @@ -1542,7 +1556,7 @@ char *delimit_lookup = ",;"; char *password_hash = (char *)g_malloc(25); - char *crypt_hash = (char *)g_malloc(25); + char *crypt_hash = (char *)g_malloc(25); char *crypt_result = NULL; unsigned char pass_hash_xor1[64]; @@ -1596,7 +1610,7 @@ magic_ptr = seed; - while (*magic_ptr != (int)NULL) { + while (*magic_ptr != '\0') { char *loc; /* Ignore parentheses. */ @@ -1649,7 +1663,7 @@ * dust on the values. */ - for (magic_cnt = magic_len-2; magic_cnt >= 0; magic_cnt--) { + for (magic_cnt = magic_len - 2; magic_cnt >= 0; magic_cnt--) { unsigned char byte1; unsigned char byte2; @@ -1665,7 +1679,7 @@ byte1 ^= byte2; magic[magic_cnt+1] = byte1; - } + } /* * Magic: Phase 3. This computes 20 bytes. The first 4 bytes are used as our magic @@ -1680,8 +1694,8 @@ x = 0; do { - unsigned int bl = 0; - unsigned int cl = magic[magic_cnt++]; + unsigned int bl = 0; + unsigned int cl = magic[magic_cnt++]; if (magic_cnt >= magic_len) break; @@ -1706,17 +1720,18 @@ /* First four bytes are magic key. */ memcpy(&magic_key_char[0], comparison_src, 4); - magic_4 = magic_key_char[0] | (magic_key_char[1]<<8) | (magic_key_char[2]<<16) | (magic_key_char[3]<<24); + magic_4 = magic_key_char[0] | (magic_key_char[1] << 8) | + (magic_key_char[2] << 16) | (magic_key_char[3] << 24); /* * Magic: Phase 4. Determine what function to use later by getting outside/inside * loop values until we match our previous buffer. */ for (x = 0; x < 65535; x++) { - int leave = 0; + int leave = 0; for (y = 0; y < 5; y++) { - unsigned char test[3]; + unsigned char test[3]; /* Calculate buffer. */ test[0] = x; @@ -1952,8 +1967,13 @@ } purple_debug_info("yahoo", "yahoo status: %d\n", yd->current_status); pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, yd->current_status, 0); - yahoo_packet_hash(pack, "sssss", 0, name, 6, resp_6, 96, resp_96, 1, - name, 135, "6,0,0,1710"); + yahoo_packet_hash(pack, "ssssss", + 0, name, + 6, resp_6, + 96, resp_96, + 1, name, + 244, YAHOO_CLIENT_VERSION_ID, + 135, YAHOO_CLIENT_VERSION); if (yd->picture_checksum) yahoo_packet_hash_int(pack, 192, yd->picture_checksum); @@ -2443,12 +2463,16 @@ case YAHOO_SERVICE_AUDIBLE: yahoo_process_audible(gc, pkt); break; - case YAHOO_SERVICE_Y7_FILETRANSFER: - yahoo_process_y7_filetransfer(gc, pkt); + case YAHOO_SERVICE_FILETRANS_15: + yahoo_process_filetrans_15(gc, pkt); break; - case YAHOO_SERVICE_Y7_FILETRANSFER_INFO: - yahoo_process_y7_filetransfer_info(gc, pkt); + case YAHOO_SERVICE_FILETRANS_INFO_15: + yahoo_process_filetrans_info_15(gc, pkt); break; + case YAHOO_SERVICE_FILETRANS_ACC_15: + yahoo_process_filetrans_acc_15(gc, pkt); + break; + default: purple_debug(PURPLE_DEBUG_ERROR, "yahoo", "Unhandled service 0x%02x\n", pkt->service); @@ -2670,11 +2694,15 @@ s = g_string_sized_new(len); while ((i = strstr(i, "Set-Cookie: "))) { + i += strlen("Set-Cookie: "); for (;*i != ';' && *i != '\0'; i++) g_string_append_c(s, *i); - + g_string_append(s, "; "); + /* Should these cookies be included too when trying for xfer? + * It seems to work without these + */ } yd->auth = g_string_free(s, FALSE); @@ -2964,6 +2992,7 @@ yd->txbuf = purple_circ_buffer_new(0); yd->friends = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, yahoo_friend_free); yd->imvironments = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + yd->xfer_peer_idstring_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); yd->confs = NULL; yd->conf_id = 2; @@ -3018,17 +3047,23 @@ } g_slist_free(yd->confs); + for (l = yd->cookies; l; l = l->next) { + g_free(l->data); + l->data=NULL; + } + g_slist_free(yd->cookies); + yd->chat_online = 0; if (yd->in_chat) yahoo_c_leave(gc, 1); /* 1 = YAHOO_CHAT_ID */ g_hash_table_destroy(yd->friends); g_hash_table_destroy(yd->imvironments); + g_hash_table_destroy(yd->xfer_peer_idstring_map); g_free(yd->chat_name); g_free(yd->cookie_y); g_free(yd->cookie_t); - g_free(yd->cookie_c); if (yd->txhandler) purple_input_remove(yd->txhandler); @@ -4130,17 +4165,13 @@ GList *yahoo_attention_types(PurpleAccount *account) { - PurpleAttentionType *attn; static GList *list = NULL; if (!list) { /* Yahoo only supports one attention command: the 'buzz'. */ /* This is index number YAHOO_BUZZ. */ - attn = g_new0(PurpleAttentionType, 1); - attn->name = _("Buzz"); - attn->incoming_description = _("%s has buzzed you!"); - attn->outgoing_description = _("Buzzing %s..."); - list = g_list_append(list, attn); + list = g_list_append(list, purple_attention_type_new("Buzz", _("Buzz"), + _("%s has buzzed you!"), _("Buzzing %s..."))); } return list;
--- a/libpurple/protocols/yahoo/yahoo.h Mon Jan 14 04:04:08 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo.h Mon Jan 14 04:09:03 2008 +0000 @@ -34,6 +34,8 @@ #define YAHOO_MAIL_URL "https://login.yahoo.com/config/login?.src=ym" #define YAHOO_XFER_HOST "filetransfer.msg.yahoo.com" #define YAHOO_XFER_PORT 80 +#define YAHOO_XFER_RELAY_HOST "relay.msg.yahoo.com" +#define YAHOO_XFER_RELAY_PORT 80 #define YAHOO_ROOMLIST_URL "http://insider.msg.yahoo.com/ycontent/" #define YAHOO_ROOMLIST_LOCALE "us" /* really we should get the list of servers from @@ -43,6 +45,11 @@ #define YAHOOJP_MAIL_URL "http://mail.yahoo.co.jp/" #define YAHOOJP_XFER_HOST "filetransfer.msg.yahoo.co.jp" #define YAHOOJP_WEBCAM_HOST "wc.yahoo.co.jp" +/*not sure, must test:*/ +#define YAHOOJP_XFER_RELAY_HOST "relay.msg.yahoo.com" +#define YAHOOJP_XFER_RELAY_PORT 80 +#define YAHOOJP_ROOMLIST_URL "http://insider.msg.yahoo.co.jp/ycontent/" +#define YAHOOJP_ROOMLIST_LOCALE "ja" #define YAHOO_AUDIBLE_URL "http://us.dl1.yimg.com/download.yahoo.com/dl/aud" @@ -67,6 +74,9 @@ #define YAHOO_STATUS_TYPE_INVISIBLE "invisible" #define YAHOO_STATUS_TYPE_MOBILE "mobile" +#define YAHOO_CLIENT_VERSION_ID "2097087" +#define YAHOO_CLIENT_VERSION "8.1.0.421" + /* Index into attention types list. */ #define YAHOO_BUZZ 0 @@ -86,7 +96,8 @@ YAHOO_STATUS_IDLE = 999, YAHOO_STATUS_WEBLOGIN = 0x5a55aa55, YAHOO_STATUS_OFFLINE = 0x5a55aa56, /* don't ask */ - YAHOO_STATUS_TYPING = 0x16 + YAHOO_STATUS_TYPING = 0x16, + YAHOO_STATUS_DISCONNECTED = 0xffffffff /* in ymsg 15. doesnt mean the normal sense of 'disconnected' */ }; struct yahoo_buddy_icon_upload_data { @@ -134,7 +145,6 @@ gsize auth_written; char *cookie_y; char *cookie_t; - char *cookie_c; int session_id; gboolean jp; gboolean wm; /* connected w/ web messenger method */ @@ -154,6 +164,8 @@ * for when we lookup people profile or photo information. */ GSList *url_datas; + GHashTable *xfer_peer_idstring_map;/*Hey, i dont know, but putting this HashTable next to friends gives a run time fault...*/ + GSList *cookies;/*contains all cookies, including _y and _t*/ }; #define YAHOO_MAX_STATUS_MESSAGE_LENGTH (255) @@ -212,6 +224,12 @@ /* yahoo_profile.c */ void yahoo_get_info(PurpleConnection *gc, const char *name); +/* needed for xfer, thought theyd be useful for other enhancements later on + Returns list of cookies stored in yahoo_data formatted as a single null terminated string + returned value must be g_freed +*/ +gchar* yahoo_get_cookies(PurpleConnection *gc); + /** * Check to see whether the sender is permitted to send *
--- a/libpurple/protocols/yahoo/yahoo_filexfer.c Mon Jan 14 04:04:08 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo_filexfer.c Mon Jan 14 04:09:03 2008 +0000 @@ -21,6 +21,7 @@ */ #include "internal.h" +#include "dnsquery.h" #include "prpl.h" #include "util.h" @@ -32,6 +33,7 @@ #include "yahoo_packet.h" #include "yahoo_filexfer.h" #include "yahoo_doodle.h" +#include "yahoo_friend.h" struct yahoo_xfer_data { gchar *host; @@ -46,81 +48,65 @@ guint tx_handler; gchar *rxqueue; guint rxlen; + gchar *xfer_peer_idstring; + gchar *xfer_idstring_for_relay; + int version; /*0 for old, 15 for Y7(YMSG 15)*/ + int info_val_249; - gboolean y7; /* true for Y7 transfers (receive only for now) */ - gchar *token; - gchar *tid; + enum { + STARTED = 0, + HEAD_REQUESTED, + HEAD_REPLY_RECEIVED, + TRANSFER_PHASE, + ACCEPTED + } status_15; + + /* contains all filenames, in case of multiple transfers, with the first + * one in the list being the current file's name (ymsg15) */ + GSList *filename_list; + GSList *size_list; /*corresponds to filename_list, with size as **STRING** */ + gboolean firstoflist; }; static void yahoo_xfer_data_free(struct yahoo_xfer_data *xd) { + PurpleConnection *gc; + struct yahoo_data *yd; + PurpleXfer *xfer; + GSList *l; + + gc = xd->gc; + yd = gc->proto_data; + + /*remove entry from map*/ + if(xd->xfer_peer_idstring) { + xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, xd->xfer_peer_idstring); + if(xfer) + g_hash_table_remove(yd->xfer_peer_idstring_map, xd->xfer_peer_idstring); + } + + /*empty file & filesize list*/ + for (l = xd->filename_list; l; l = l->next) { + g_free(l->data); + l->data=NULL; + } + for (l = xd->size_list; l; l = l->next) { + g_free(l->data); + l->data=NULL; + } + g_slist_free(xd->filename_list); + g_slist_free(xd->size_list); + g_free(xd->host); g_free(xd->path); g_free(xd->txbuf); - g_free(xd->token); - g_free(xd->tid); + g_free(xd->xfer_peer_idstring); + g_free(xd->xfer_idstring_for_relay); if (xd->tx_handler) purple_input_remove(xd->tx_handler); g_free(xd); } - -static void yahoo_xfer_y7_request_next_file(PurpleXfer *xfer) -{ - struct yahoo_packet *pack; - struct yahoo_xfer_data *xd = xfer->data; - PurpleConnection *gc = xd->gc; - struct yahoo_data *yd = gc->proto_data; - - g_return_if_fail(xd->y7); - - pack = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFER_ACCEPT, YAHOO_STATUS_AVAILABLE, 0); - yahoo_packet_hash(pack, "sssi", - 1, purple_connection_get_display_name(xd->gc), - 5, xfer->who, - 265, xd->tid, - 271, 1); - yahoo_packet_send_and_free(pack, yd); -} - -static void yahoo_xfer_y7_cancel_receive(PurpleXfer *xfer) -{ - struct yahoo_packet *pack; - struct yahoo_xfer_data *xd = xfer->data; - PurpleConnection *gc = xd->gc; - struct yahoo_data *yd = gc->proto_data; - - g_return_if_fail(xd->y7); - - pack = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFER_ACCEPT, -1, 0); - yahoo_packet_hash(pack, "sssi", - 1, purple_connection_get_display_name(gc), - 5, xfer->who, - 265, xd->tid, - 66, -1); - yahoo_packet_send_and_free(pack, yd); -} - -static void yahoo_xfer_y7_accept_file(PurpleXfer *xfer) -{ - struct yahoo_packet *pack; - struct yahoo_xfer_data *xd = xfer->data; - PurpleConnection *gc = xd->gc; - struct yahoo_data *yd = gc->proto_data; - - g_return_if_fail(xd->y7); - - pack = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFER_ACCEPT, YAHOO_STATUS_AVAILABLE, 0); - yahoo_packet_hash(pack, "ssssis", - 1, purple_connection_get_display_name(gc), - 5, xfer->who, /* XXX this needs an accessor */ - 265, xd->tid, - 27, purple_xfer_get_filename(xfer), /* XXX this might be of incorrect encoding */ - 249, 3, - 251, xd->token); - yahoo_packet_send_and_free(pack, yd); -} - static void yahoo_receivefile_send_cb(gpointer data, gint source, PurpleInputCondition condition) { PurpleXfer *xfer; @@ -160,7 +146,6 @@ { PurpleXfer *xfer; struct yahoo_xfer_data *xd; - struct yahoo_data *yd; purple_debug(PURPLE_DEBUG_INFO, "yahoo", "AAA - in yahoo_receivefile_connected\n"); @@ -176,22 +161,11 @@ } xfer->fd = source; - yd = xd->gc->proto_data; /* The first time we get here, assemble the tx buffer */ if (xd->txbuflen == 0) { - if (!xd->y7) - xd->txbuf = g_strdup_printf("GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n", - xd->path, xd->host); - else - xd->txbuf = g_strdup_printf("GET /%s HTTP/1.0\r\n" - "Connection: close\r\n" - "Accept: */*\r\n" - "Host: %s\r\n" - "Cookie: Y=%s; T=%s\r\n" - "\r\n", - xd->path, xd->host, yd->cookie_y, yd->cookie_t); - purple_debug(PURPLE_DEBUG_INFO, "yahoo_filexfer", "HTTP request: [%s]\n", xd->txbuf); + xd->txbuf = g_strdup_printf("GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n", + xd->path, xd->host); xd->txbuflen = strlen(xd->txbuf); xd->txbuf_written = 0; } @@ -356,9 +330,6 @@ } } } else { - if (xfer_data->y7) - yahoo_xfer_y7_accept_file(xfer); - xfer->fd = -1; if (purple_proxy_connect(NULL, account, xfer_data->host, xfer_data->port, yahoo_receivefile_connected, xfer) == NULL) { @@ -369,23 +340,67 @@ } } +static void yahoo_xfer_init_15(PurpleXfer *xfer) +{ + struct yahoo_xfer_data *xfer_data; + PurpleConnection *gc; + PurpleAccount *account; + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + xfer_data = xfer->data; + gc = xfer_data->gc; + yd = gc->proto_data; + account = purple_connection_get_account(gc); + + if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) { + gchar *filename; + filename = g_path_get_basename(purple_xfer_get_local_filename(xfer)); + pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15, + YAHOO_STATUS_AVAILABLE, + yd->session_id); + yahoo_packet_hash(pkt, "sssiiiisiii", + 1, purple_normalize(account, purple_account_get_username(account)), + 5, xfer->who, + 265, xfer_data->xfer_peer_idstring, + 222, 1, + 266, 1, + 302, 268, + 300, 268, + 27, filename, + 28, xfer->size, + 301, 268, + 303, 268); + g_free(filename); + } else { + if(xfer_data->firstoflist == TRUE) { + pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15, + YAHOO_STATUS_AVAILABLE, yd->session_id); + + yahoo_packet_hash(pkt, "sssi", + 1, purple_normalize(account, purple_account_get_username(account)), + 5, xfer->who, + 265, xfer_data->xfer_peer_idstring, + 222, 3); + } else { + pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_ACC_15, + YAHOO_STATUS_AVAILABLE, yd->session_id); + + yahoo_packet_hash(pkt, "sssi", + 1, purple_normalize(account, purple_account_get_username(account)), + 5, xfer->who, + 265, xfer_data->xfer_peer_idstring, + 271, 1); + } + } + yahoo_packet_send_and_free(pkt, yd); +} + static void yahoo_xfer_start(PurpleXfer *xfer) { /* We don't need to do anything here, do we? */ } -static void yahoo_xfer_end(PurpleXfer *xfer) -{ - struct yahoo_xfer_data *xfer_data; - - xfer_data = xfer->data; - - if (xfer_data) - yahoo_xfer_data_free(xfer_data); - xfer->data = NULL; - -} - static guint calculate_length(const gchar *l, size_t len) { int i; @@ -418,8 +433,6 @@ if ((purple_xfer_get_size(xfer) > 0) && (purple_xfer_get_bytes_sent(xfer) >= purple_xfer_get_size(xfer))) { purple_xfer_set_completed(xfer, TRUE); - if (xd->y7) - yahoo_xfer_y7_request_next_file(xfer); return 0; } else return -1; @@ -499,6 +512,42 @@ xfer_data = xfer->data; + if(purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL && xfer_data->version == 15) + { + PurpleConnection *gc; + PurpleAccount *account; + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + gc = xfer_data->gc; + yd = gc->proto_data; + account = purple_connection_get_account(gc); + if(xfer_data->xfer_idstring_for_relay) /* hack to see if file trans acc/info packet has been received */ + { + pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15, + YAHOO_STATUS_DISCONNECTED, + yd->session_id); + yahoo_packet_hash(pkt, "sssi", + 1, purple_normalize(account, purple_account_get_username(account)), + 5, xfer->who, + 265, xfer_data->xfer_peer_idstring, + 66, -1); + } + else + { + pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15, + YAHOO_STATUS_AVAILABLE, + yd->session_id); + yahoo_packet_hash(pkt, "sssi", + 1, purple_normalize(account, purple_account_get_username(account)), + 5, xfer->who, + 265, xfer_data->xfer_peer_idstring, + 222, 2); + } + yahoo_packet_send_and_free(pkt, yd); + } + + if (xfer_data) yahoo_xfer_data_free(xfer_data); xfer->data = NULL; @@ -510,22 +559,145 @@ xfer_data = xfer->data; - if (xfer_data) { - if (xfer_data->y7) - yahoo_xfer_y7_cancel_receive(xfer); + if(purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL && xfer_data->version == 15) + { + + PurpleConnection *gc; + PurpleAccount *account; + struct yahoo_data *yd; + struct yahoo_packet *pkt; + + gc = xfer_data->gc; + yd = gc->proto_data; + account = purple_connection_get_account(gc); + if(!xfer_data->xfer_idstring_for_relay) /* hack to see if file trans acc/info packet has been received */ + { + pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15, + YAHOO_STATUS_AVAILABLE, + yd->session_id); + yahoo_packet_hash(pkt, "sssi", + 1, purple_normalize(account, purple_account_get_username(account)), + 5, xfer->who, + 265, xfer_data->xfer_peer_idstring, + 222, 4); + } + else + { + pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15, + YAHOO_STATUS_DISCONNECTED, + yd->session_id); + yahoo_packet_hash(pkt, "sssi", + 1, purple_normalize(account, purple_account_get_username(account)), + 5, xfer->who, + 265, xfer_data->xfer_peer_idstring, + 66, -1); + } + yahoo_packet_send_and_free(pkt, yd); + } + + if (xfer_data) yahoo_xfer_data_free(xfer_data); - } xfer->data = NULL; } -static void yahoo_xfer_request_denied(PurpleXfer *xfer) +static void yahoo_xfer_end(PurpleXfer *xfer_old) { struct yahoo_xfer_data *xfer_data; + PurpleXfer *xfer = NULL; + PurpleConnection *gc; + struct yahoo_data *yd; - xfer_data = xfer->data; + xfer_data = xfer_old->data; + if(xfer_data && xfer_data->version == 15 + && purple_xfer_get_type(xfer_old) == PURPLE_XFER_RECEIVE + && xfer_data->filename_list) { + + /* removing top of filename & size list completely */ + g_free( xfer_data->filename_list->data ); + g_free( xfer_data->size_list->data ); + + xfer_data->filename_list->data = NULL; + xfer_data->size_list->data = NULL; + + xfer_data->filename_list = g_slist_delete_link(xfer_data->filename_list, xfer_data->filename_list); + xfer_data->size_list = g_slist_delete_link(xfer_data->size_list, xfer_data->size_list); + + /* if there are still more files */ + if(xfer_data->filename_list) + { + gchar* filename; + long filesize; + + filename = xfer_data->filename_list->data; + filesize = atol( xfer_data->size_list->data ); + + gc = xfer_data->gc; + yd = gc->proto_data; - if (xfer_data->y7) - yahoo_xfer_y7_cancel_receive(xfer); + /* setting up xfer_data for next file's tranfer */ + g_free(xfer_data->host); + g_free(xfer_data->path); + g_free(xfer_data->txbuf); + g_free(xfer_data->rxqueue); + g_free(xfer_data->xfer_idstring_for_relay); + if (xfer_data->tx_handler) + purple_input_remove(xfer_data->tx_handler); + xfer_data->host = NULL; + xfer_data->host = NULL; + xfer_data->port = 0; + xfer_data->expires = 0; + xfer_data->started = FALSE; + xfer_data->txbuf = NULL; + xfer_data->txbuflen = 0; + xfer_data->txbuf_written = 0; + xfer_data->tx_handler = 0; + xfer_data->rxqueue = NULL; + xfer_data->rxlen = 0; + xfer_data->xfer_idstring_for_relay = NULL; + xfer_data->info_val_249 = 0; + xfer_data->status_15 = STARTED; + xfer_data->firstoflist = FALSE; + + /* Dereference xfer_data from old xfer */ + xfer_old->data = NULL; + + /* Build the file transfer handle. */ + xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, xfer_old->who); + + + if (xfer) { + /* Set the info about the incoming file. */ + char *utf8_filename = yahoo_string_decode(gc, filename, TRUE); + purple_xfer_set_filename(xfer, utf8_filename); + g_free(utf8_filename); + purple_xfer_set_size(xfer, filesize); + + xfer->data = xfer_data; + + /* Setup our I/O op functions */ + purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15); + purple_xfer_set_start_fnc(xfer, yahoo_xfer_start); + purple_xfer_set_end_fnc(xfer, yahoo_xfer_end); + purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send); + purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv); + purple_xfer_set_read_fnc(xfer, yahoo_xfer_read); + purple_xfer_set_write_fnc(xfer, yahoo_xfer_write); + purple_xfer_set_request_denied_fnc(xfer,yahoo_xfer_cancel_recv); + + /*update map to current xfer*/ + g_hash_table_remove(yd->xfer_peer_idstring_map, xfer_data->xfer_peer_idstring); + g_hash_table_insert(yd->xfer_peer_idstring_map, xfer_data->xfer_peer_idstring, xfer); + + /* Now perform the request */ + purple_xfer_request(xfer); + } + return; + } + } + if (xfer_data) + yahoo_xfer_data_free(xfer_data); + xfer_old->data = NULL; + } void yahoo_process_p2pfilexfer(PurpleConnection *gc, struct yahoo_packet *pkt) @@ -721,165 +893,6 @@ } } -void yahoo_process_y7_filetransfer(PurpleConnection *gc, struct yahoo_packet *pkt) -{ - struct yahoo_data *yd = gc->proto_data; - char *who = NULL, *name = NULL; - int ttype = 0; - char *tid = NULL; - GSList *l = pkt->hash; - - while (l) { - struct yahoo_pair *pair = l->data; - - switch (pair->key) { - case 4: - /* them */ - who = pair->value; - break; - case 5: - /* us */ - name = pair->value; - break; - case 222: - /* 1=send, 2=cancel, 3=accept, 4=reject */ - if(pair->value) - ttype = atoi(pair->value); - break; - case 265: - /* transfer ID */ - tid = pair->value; - break; - case 266: - /* number of files */ - break; - case 27: - /* filename */ - break; - case 28: - /* filesize */ - break; - } - - l = l->next; - } - if (ttype == 1 && tid) { - /* We auto-accept all offers here, and ask the user about each individual - * file in yahoo_process_y7_filetransfer_info. This works fine for receiving - * a single file; when receiving multiple canceling one in the middle - * will also cancel the rest of them. - * Maybe TODO: UI and API allowing transfer of multiple files as a package. */ - struct yahoo_packet *pack; - pack = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFER, YAHOO_STATUS_AVAILABLE, 0); - yahoo_packet_hash(pack, "sssi", 1, name, 5, who, 265, tid, 222, 3); - yahoo_packet_send_and_free(pack, yd); - } -} - -void yahoo_process_y7_filetransfer_info(PurpleConnection *gc, struct yahoo_packet *pkt) -{ - struct yahoo_data *yd = gc->proto_data; - char *who = NULL, *name = NULL; - int medium = 0; - char *tid = NULL, *server_host = NULL, *server_token = NULL, *filename = NULL; - GSList *l = pkt->hash; - struct yahoo_packet *pack; - PurpleXfer *xfer; - struct yahoo_xfer_data *xfer_data; - - while (l) { - struct yahoo_pair *pair = l->data; - - switch (pair->key) { - case 4: - /* them */ - who = pair->value; - break; - case 5: - /* us */ - name = pair->value; - break; - case 249: - /* 1=p2p, 3=reflection server */ - if(pair->value) - medium = atoi(pair->value); - break; - case 265: - /* transfer ID */ - tid = pair->value; - break; - case 27: - filename = pair->value; - break; - case 250: - server_host = pair->value; - break; - case 251: - server_token = pair->value; - break; - } - - l = l->next; - } - if (medium == 1) { - /* reject P2P transfers */ - pack = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFER_ACCEPT, YAHOO_STATUS_AVAILABLE, 0); - yahoo_packet_hash(pack, "sssi", 1, name, 5, who, 265, tid, 66, -3); - yahoo_packet_send_and_free(pack, yd); - return; - } - - if (medium != 3) { - purple_debug_error("yahoo", "Unexpected medium %d.\n", medium); - /* weird */ - return; - } - - /* Setup the Yahoo-specific file transfer data */ - xfer_data = g_new0(struct yahoo_xfer_data, 1); - xfer_data->gc = gc; - xfer_data->host = g_strdup(server_host); - xfer_data->token = g_strdup(server_token); - xfer_data->tid = g_strdup(tid); - xfer_data->port = 80; - xfer_data->y7 = TRUE; - - /* TODO: full urlencode here */ - server_token = purple_strreplace(server_token, "\002", "%02"); - xfer_data->path = g_strdup_printf("relay?token=%s&sender=%s&recver=%s", - server_token, who, name); - g_free(server_token); - - purple_debug_misc("yahoo_filexfer", "Host is %s, port is %d, path is %s.\n", - xfer_data->host, xfer_data->port, xfer_data->path); - - /* Build the file transfer handle. */ - xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, who); - xfer->data = xfer_data; - - /* Set the info about the incoming file. */ - { - char *utf8_filename = yahoo_string_decode(gc, filename, TRUE); - purple_xfer_set_filename(xfer, utf8_filename); - g_free(utf8_filename); - } - - /* purple_xfer_set_size(xfer, filesize); */ - - /* Setup our I/O op functions */ - purple_xfer_set_init_fnc(xfer, yahoo_xfer_init); - purple_xfer_set_start_fnc(xfer, yahoo_xfer_start); - purple_xfer_set_end_fnc(xfer, yahoo_xfer_end); - purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send); - purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv); - purple_xfer_set_read_fnc(xfer, yahoo_xfer_read); - purple_xfer_set_write_fnc(xfer, yahoo_xfer_write); - purple_xfer_set_request_denied_fnc(xfer, yahoo_xfer_request_denied); - - /* Now perform the request */ - purple_xfer_request(xfer); -} - PurpleXfer *yahoo_new_xfer(PurpleConnection *gc, const char *who) { PurpleXfer *xfer; @@ -909,15 +922,641 @@ return xfer; } +static gchar* yahoo_xfer_new_xfer_id() +{ + gchar *ans; + int i,j; + ans = g_strnfill(24, ' '); + ans[23] = '$'; + ans[22] = '$'; + for(i = 0; i < 22; i++) + { + j = g_random_int_range (0,61); + if(j < 26) + ans[i] = j + 'a'; + else if(j < 52) + ans[i] = j - 26 + 'A'; + else + ans[i] = j - 52 + '0'; + } + return ans; +} + +static void yahoo_xfer_dns_connected_15(GSList *hosts, gpointer data, const char *error_message) +{ + PurpleXfer *xfer; + struct yahoo_xfer_data *xd; + struct sockaddr_in *addr; + struct yahoo_packet *pkt; + long actaddr; + long a,b,c,d; + PurpleConnection *gc; + PurpleAccount *account; + struct yahoo_data *yd; + gchar *url; + gchar *filename; + + if (!(xfer = data)) + return; + if (!(xd = xfer->data)) + return; + gc = xd->gc; + account = purple_connection_get_account(gc); + yd = gc->proto_data; + + if(!hosts) + { + purple_debug_error("yahoo", "Unable to find an IP address for relay.msg.yahoo.com\n"); + purple_xfer_cancel_remote(xfer); + return; + } + + /* Discard the length... */ + hosts = g_slist_remove(hosts, hosts->data); + if(!hosts) + { + purple_debug_error("yahoo", "Unable to find an IP address for relay.msg.yahoo.com\n"); + purple_xfer_cancel_remote(xfer); + return; + } + + /*TODO:actually, u must try with addr no.1 , if its not working addr no.2 .....*/ + addr = hosts->data; + actaddr = addr->sin_addr.s_addr; + d = actaddr % 256; + actaddr = (actaddr - d) / 256; + c = actaddr % 256; + actaddr = (actaddr - c) / 256; + b = actaddr % 256; + actaddr = (actaddr - b) / 256; + a = actaddr; + if(yd->jp) + xd->port = YAHOOJP_XFER_RELAY_PORT; + else + xd->port = YAHOO_XFER_RELAY_PORT; + + url = g_strdup_printf("%ld.%ld.%ld.%ld", d, c, b, a); + if (!purple_url_parse(url, &(xd->host), &(xd->port), &(xd->path), NULL, NULL)) { + purple_xfer_cancel_remote(xfer); + return; + } + g_free(url); + /* Free the address... */ + g_free(hosts->data); + hosts = g_slist_remove(hosts, hosts->data); + addr = NULL; + while (hosts != NULL) + { + /* Discard the length... */ + hosts = g_slist_remove(hosts, hosts->data); + /* Free the address... */ + g_free(hosts->data); + hosts = g_slist_remove(hosts, hosts->data); + } + + pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15, YAHOO_STATUS_AVAILABLE, yd->session_id); + filename = g_path_get_basename(purple_xfer_get_local_filename(xfer)); + + yahoo_packet_hash(pkt, "ssssis", + 1, purple_normalize(account, purple_account_get_username(account)), + 5, xfer->who, + 265, xd->xfer_peer_idstring, + 27, filename, + 249, 3, + 250, xd->host); + + g_free(filename); + yahoo_packet_send_and_free(pkt, yd); +} + + void yahoo_send_file(PurpleConnection *gc, const char *who, const char *file) { + struct yahoo_xfer_data *xfer_data; + struct yahoo_data *yd; + int ver = 0; PurpleXfer *xfer = yahoo_new_xfer(gc, who); + YahooFriend *yf = yahoo_friend_find(gc, who); + /* To determine whether client uses ymsg 15 i.e. client is higher than YM 7 */ + if(yf && yf->version_id > 500000) + ver=15; g_return_if_fail(xfer != NULL); + if(ver == 15) { + yd = gc->proto_data; + xfer_data = xfer->data; + xfer_data->status_15 = STARTED; + purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15); + xfer_data->version = 15; + xfer_data->xfer_peer_idstring = yahoo_xfer_new_xfer_id(); + g_hash_table_insert(yd->xfer_peer_idstring_map, xfer_data->xfer_peer_idstring, xfer); + } + /* Now perform the request */ if (file) purple_xfer_request_accepted(xfer, file); else purple_xfer_request(xfer); } + +static void yahoo_xfer_connected_15(gpointer data, gint source, const gchar *error_message);/*using this in recv_cb*/ +static void yahoo_xfer_recv_cb_15(gpointer data, gint source, PurpleInputCondition condition) +{ + PurpleXfer *xfer; + struct yahoo_xfer_data *xd; + int did; + gchar* buf; + gchar* t; + PurpleAccount *account; + PurpleConnection *gc; + + xfer = data; + xd = xfer->data; + account = purple_connection_get_account(xd->gc); + gc = xd->gc; + + buf=g_strnfill(1000, 0); + while((did = read(source, buf, 998)) > 0) + { + xd->txbuflen += did; + buf[did] = '\0'; + t = xd->txbuf; + xd->txbuf = g_strconcat(t,buf,NULL); + g_free(t); + } + g_free(buf); + + if (did < 0 && errno == EAGAIN) return; + else if (did < 0) { + purple_debug_error("yahoo", "Unable to write in order to start ft errno = %d\n", errno); + purple_xfer_cancel_remote(xfer); + return; + } + + purple_input_remove(xd->tx_handler); + xd->tx_handler = 0; + xd->txbuflen = 0; + + if(xd->status_15 == HEAD_REQUESTED) { + xd->status_15 = HEAD_REPLY_RECEIVED; + close(source);/*Is this required?*/ + g_free(xd->txbuf); + xd->txbuf = NULL; + if (purple_proxy_connect(NULL, account, xd->host, xd->port, yahoo_xfer_connected_15, xfer) == NULL) + { + purple_notify_error(gc, NULL, _("File Transfer Failed"), + _("Unable to establish file descriptor.")); + purple_xfer_cancel_remote(xfer); + } + } else { + purple_debug_error("yahoo","Unrecognized yahoo file transfer mode and stage (ymsg15):%d,%d\n", + purple_xfer_get_type(xfer), + xd->status_15); + return; + } +} + +static void yahoo_xfer_send_cb_15(gpointer data, gint source, PurpleInputCondition condition) +{ + PurpleXfer *xfer; + struct yahoo_xfer_data *xd; + int remaining, written; + + xfer = data; + xd = xfer->data; + remaining = xd->txbuflen - xd->txbuf_written; + written = write(source, xd->txbuf + xd->txbuf_written, remaining); + + if (written < 0 && errno == EAGAIN) + written = 0; + else if (written <= 0) { + purple_debug_error("yahoo", "Unable to write in order to start ft errno = %d\n", errno); + purple_xfer_cancel_remote(xfer); + return; + } + + if (written < remaining) { + xd->txbuf_written += written; + return; + } + + purple_input_remove(xd->tx_handler); + xd->tx_handler = 0; + g_free(xd->txbuf); + xd->txbuf = NULL; + xd->txbuflen = 0; + xd->txbuf_written = 0; + + if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == STARTED) + { + xd->status_15 = HEAD_REQUESTED; + xd->tx_handler = purple_input_add(source, PURPLE_INPUT_READ, yahoo_xfer_recv_cb_15, xfer); + yahoo_xfer_recv_cb_15(xfer, source, PURPLE_INPUT_READ); + } + else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == HEAD_REPLY_RECEIVED) + { + xd->status_15 = TRANSFER_PHASE; + xfer->fd = source; + purple_xfer_start(xfer, source, NULL, 0); + } + else if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && xd->status_15 == ACCEPTED) + { + xd->status_15 = TRANSFER_PHASE; + xfer->fd = source; + purple_xfer_start(xfer, source, NULL, 0); + } + else + { + purple_debug_error("yahoo", "Unrecognized yahoo file transfer mode and stage (ymsg15):%d,%d\n", purple_xfer_get_type(xfer), xd->status_15); + return; + } + +} + + +static void yahoo_xfer_connected_15(gpointer data, gint source, const gchar *error_message) +{ + PurpleXfer *xfer; + struct yahoo_xfer_data *xd; + PurpleAccount *account; + struct yahoo_data* yd; + + if (!(xfer = data)) + return; + if (!(xd = xfer->data)) + return; + yd = xd->gc->proto_data; + account = purple_connection_get_account(xd->gc); + if ((source < 0) || (xd->path == NULL) || (xd->host == NULL)) { + purple_xfer_error(PURPLE_XFER_RECEIVE, purple_xfer_get_account(xfer), + xfer->who, _("Unable to connect.")); + purple_xfer_cancel_remote(xfer); + return; + } + /* The first time we get here, assemble the tx buffer */ + if (xd->txbuflen == 0) + { + gchar* cookies; + cookies = yahoo_get_cookies(xd->gc); + if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && xd->status_15 == ACCEPTED) + { + xd->txbuf = g_strdup_printf("POST /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\nCookie:%s\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 5.5)\r\nHost: %s\r\nContent-Length: %ld\r\nCache-Control: no-cache\r\n\r\n", + purple_url_encode(xd->xfer_idstring_for_relay), + purple_normalize(account, purple_account_get_username(account)), + xfer->who, + cookies, + xd->host, + (long int)xfer->size); + } + else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == STARTED) + { + xd->txbuf = g_strdup_printf("HEAD /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\nAccept:*/*\r\nCookie:%s\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 5.5)\r\nHost:%s\r\nContent-Length: 0\r\nCache-Control: no-cache\r\n\r\n", + purple_url_encode(xd->xfer_idstring_for_relay), + purple_normalize(account, purple_account_get_username(account)), + xfer->who, + cookies, + xd->host); + } + else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == HEAD_REPLY_RECEIVED) + { + xd->txbuf = g_strdup_printf("GET /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\nCookie:%s\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 5.5)\r\nHost:%s\r\nConnection: Keep-Alive\r\n\r\n", + purple_url_encode(xd->xfer_idstring_for_relay), + purple_normalize(account, purple_account_get_username(account)), + xfer->who, + cookies, + xd->host); + } + else + { + purple_debug_error("yahoo", "Unrecognized yahoo file transfer mode and stage (ymsg15):%d,%d\n", purple_xfer_get_type(xfer), xd->status_15); + g_free(cookies); + return; + } + xd->txbuflen = strlen(xd->txbuf); + xd->txbuf_written = 0; + g_free(cookies); + } + + if (!xd->tx_handler) + { + xd->tx_handler = purple_input_add(source, PURPLE_INPUT_WRITE, + yahoo_xfer_send_cb_15, xfer); + yahoo_xfer_send_cb_15(xfer, source, PURPLE_INPUT_WRITE); + } +} + +void yahoo_process_filetrans_15(PurpleConnection *gc, struct yahoo_packet *pkt) +{ + char *from = NULL; + char *to = NULL; + char *imv = NULL; + long val_222 = 0L; + PurpleXfer *xfer; + struct yahoo_data *yd; + struct yahoo_xfer_data *xfer_data; + char *service = NULL; + char *filename = NULL; + char *xfer_peer_idstring = NULL; + unsigned long filesize = 0L; + GSList *l; + GSList *filename_list = NULL; + GSList *size_list = NULL; + int nooffiles = 0; + + yd = gc->proto_data; + + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + + switch (pair->key) { + case 4: + from = pair->value; + break; + case 5: + to = pair->value; + break; + case 265: + xfer_peer_idstring = pair->value; + break; + case 27: + filename_list = g_slist_prepend(filename_list, g_strdup(pair->value)); + nooffiles++; + break; + case 28: + size_list = g_slist_prepend(size_list, g_strdup(pair->value)); + break; + case 222: + val_222 = atol(pair->value); + /* 1=send, 2=cancel, 3=accept, 4=reject */ + break; + + /*check for p2p and imviron .... not sure it comes by this service packet. Since it was bundled with filexfer in old ymsg version, still keeping it.*/ + case 49: + service = pair->value; + break; + case 63: + imv = pair->value; + break; + /*end check*/ + + } + } + if(!xfer_peer_idstring) + return; + + if(val_222 == 2 || val_222 == 4) + { + xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, + xfer_peer_idstring); + if(!xfer) return; + purple_xfer_cancel_remote(xfer); + return; + } + if(val_222 == 3) + { + xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, + xfer_peer_idstring); + if(!xfer) + return; + /* + * In the file trans info packet tht we must reply with , we are supposed to mention the ip address... + * purple connect does not give me a way of finding the ip address... + * so, purple dnsquery is used... but retries, trying with next ip address etc. is not implemented..TODO + */ + if (yd->jp) + { + purple_dnsquery_a(YAHOOJP_XFER_RELAY_HOST, YAHOOJP_XFER_RELAY_PORT, yahoo_xfer_dns_connected_15, xfer); + } + else + { + purple_dnsquery_a(YAHOO_XFER_RELAY_HOST, YAHOO_XFER_RELAY_PORT, yahoo_xfer_dns_connected_15, xfer); + } + return; + } + + /*processing for p2p and imviron .... not sure it comes by this service packet. Since it was bundled with filexfer in old ymsg version, still keeping it.*/ + /* + * The remote user has changed their IMVironment. We + * record it for later use. + */ + if (from && imv && service && (strcmp("IMVIRONMENT", service) == 0)) { + g_hash_table_replace(yd->imvironments, g_strdup(from), g_strdup(imv)); + return; + } + + if (pkt->service == YAHOO_SERVICE_P2PFILEXFER) { + if (service && (strcmp("FILEXFER", service) != 0)) { + purple_debug_misc("yahoo", "unhandled service 0x%02x\n", pkt->service); + return; + } + } + /*end processing*/ + + if(!filename_list) + return; + /* have to change list into order in which client at other end sends */ + filename_list = g_slist_reverse(filename_list); + size_list = g_slist_reverse(size_list); + filename = filename_list->data; + filesize = atol(size_list->data); + + if(!from) return; + xfer_data = g_new0(struct yahoo_xfer_data, 1); + xfer_data->version = 15; + xfer_data->firstoflist = TRUE; + xfer_data->gc = gc; + xfer_data->xfer_peer_idstring = g_strdup(xfer_peer_idstring); + xfer_data->filename_list = filename_list; + xfer_data->size_list = size_list; + + /* Build the file transfer handle. */ + xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, from); + xfer->message = NULL; + + if (xfer) + { + /* Set the info about the incoming file. */ + char *utf8_filename = yahoo_string_decode(gc, filename, TRUE); + purple_xfer_set_filename(xfer, utf8_filename); + g_free(utf8_filename); + purple_xfer_set_size(xfer, filesize); + + xfer->data = xfer_data; + + + /* Setup our I/O op functions */ + purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15); + purple_xfer_set_start_fnc(xfer, yahoo_xfer_start); + purple_xfer_set_end_fnc(xfer, yahoo_xfer_end); + purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send); + purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv); + purple_xfer_set_read_fnc(xfer, yahoo_xfer_read); + purple_xfer_set_write_fnc(xfer, yahoo_xfer_write); + purple_xfer_set_request_denied_fnc(xfer,yahoo_xfer_cancel_recv); + + g_hash_table_insert(yd->xfer_peer_idstring_map, + xfer_data->xfer_peer_idstring, + xfer); + + if(nooffiles > 1) { + gchar* message; + message = g_strdup_printf(_("%s is trying to send you a group of %d files.\n"), xfer->who, nooffiles); + purple_xfer_conversation_write(xfer, message, FALSE); + g_free(message); + } + /* Now perform the request */ + purple_xfer_request(xfer); + } +} + +void yahoo_process_filetrans_info_15(PurpleConnection *gc, struct yahoo_packet *pkt) +{ + char *from = NULL; + char *to = NULL; + char *url = NULL; + long val_249 = 0; + long val_66 = 0; + PurpleXfer *xfer; + struct yahoo_data *yd; + struct yahoo_xfer_data *xfer_data; + char *filename = NULL; + char *xfer_peer_idstring = NULL; + char *xfer_idstring_for_relay = NULL; + GSList *l; + struct yahoo_packet *pkt_to_send; + PurpleAccount *account; + + yd = gc->proto_data; + + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + + switch (pair->key) { + case 4: + from = pair->value; + break; + case 5: + to = pair->value; + break; + case 265: + xfer_peer_idstring = pair->value; + break; + case 27: + filename = pair->value; + break; + case 66: + val_66 = strtol(pair->value, NULL, 10); + break; + case 249: + val_249 = strtol(pair->value, NULL, 10); /* + * really pissed off with this- i hv seen 2 occurences of this + * being 1(its normally 3) - and in those cases, the url + * format and corresponding processing seems to be different + * (i havent tested - couldnt reproduce a 1), although i + * guess its easier. + */ + break; + case 250: + url = pair->value; + break; + case 251: + xfer_idstring_for_relay = pair->value; + break; + } + } + + if(!xfer_peer_idstring) + return; + + xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, xfer_peer_idstring); + + if(!xfer) return; + + if(val_66==-1) + { + purple_xfer_cancel_remote(xfer); + return; + } + + xfer_data = xfer->data; + + xfer_data->info_val_249 = val_249; + xfer_data->xfer_idstring_for_relay = g_strdup(xfer_idstring_for_relay); + if (!purple_url_parse(url, &(xfer_data->host), &(xfer_data->port), &(xfer_data->path), NULL, NULL)) { + purple_xfer_cancel_remote(xfer); + return; + } + + account = purple_connection_get_account(xfer_data->gc); + + pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_ACC_15, + YAHOO_STATUS_AVAILABLE, yd->session_id); + + yahoo_packet_hash(pkt_to_send, "ssssisi", + 1, purple_normalize(account, purple_account_get_username(account)), + 5, xfer->who, + 265, xfer_data->xfer_peer_idstring, + 27, xfer->filename, + 249, xfer_data->info_val_249, + 251, xfer_data->xfer_idstring_for_relay, + 222, 3); + + yahoo_packet_send_and_free(pkt_to_send, yd); + if (purple_proxy_connect(NULL, account, xfer_data->host, xfer_data->port, + yahoo_xfer_connected_15, xfer) == NULL) { + purple_notify_error(gc, NULL, _("File Transfer Failed"), + _("Unable to establish file descriptor.")); + purple_xfer_cancel_remote(xfer); + } + +} +/*TODO: Check filename etc. No probs till some hacker comes in the way*/ +void yahoo_process_filetrans_acc_15(PurpleConnection *gc, struct yahoo_packet *pkt) +{ + gchar *xfer_peer_idstring = NULL; + gchar *xfer_idstring_for_relay = NULL; + PurpleXfer *xfer; + struct yahoo_data *yd; + struct yahoo_xfer_data *xfer_data; + GSList *l; + PurpleAccount *account; + long val_66 = 0; + + yd = gc->proto_data; + for (l = pkt->hash; l; l = l->next) { + struct yahoo_pair *pair = l->data; + + switch (pair->key) { + case 251: + xfer_idstring_for_relay = pair->value; + break; + case 265: + xfer_peer_idstring = pair->value; + break; + case 66: + val_66 = atol(pair->value); + } + } + + xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, xfer_peer_idstring); + if(!xfer) return; + + if(val_66 == -1 || !(xfer_idstring_for_relay)) + { + purple_xfer_cancel_remote(xfer); + return; + } + + xfer_data = xfer->data; + xfer_data->xfer_idstring_for_relay = g_strdup(xfer_idstring_for_relay); + xfer_data->status_15 = ACCEPTED; + account = purple_connection_get_account(gc); + + if (purple_proxy_connect(NULL, account, xfer_data->host, xfer_data->port, + yahoo_xfer_connected_15, xfer) == NULL) + { + purple_notify_error(gc, NULL, _("File Transfer Failed"),_("Unable to connect")); + purple_xfer_cancel_remote(xfer); + } +}
--- a/libpurple/protocols/yahoo/yahoo_filexfer.h Mon Jan 14 04:04:08 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo_filexfer.h Mon Jan 14 04:09:03 2008 +0000 @@ -30,16 +30,6 @@ void yahoo_process_p2pfilexfer( PurpleConnection *gc, struct yahoo_packet *pkt ); /** - * Process ymsg version 7 file receive invites. - */ -void yahoo_process_y7_filetransfer(PurpleConnection *gc, struct yahoo_packet *pkt); - -/** - * Process ymsg version 7 file receive connection setups. - */ -void yahoo_process_y7_filetransfer_info(PurpleConnection *gc, struct yahoo_packet *pkt); - -/** * Process ymsg file receive invites. */ void yahoo_process_filetransfer(PurpleConnection *gc, struct yahoo_packet *pkt); @@ -61,4 +51,8 @@ */ void yahoo_send_file(PurpleConnection *gc, const char *who, const char *file); +void yahoo_process_filetrans_15(PurpleConnection *gc, struct yahoo_packet *pkt); +void yahoo_process_filetrans_info_15(PurpleConnection *gc, struct yahoo_packet *pkt); +void yahoo_process_filetrans_acc_15(PurpleConnection *gc, struct yahoo_packet *pkt); + #endif
--- a/libpurple/protocols/yahoo/yahoo_friend.h Mon Jan 14 04:04:08 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo_friend.h Mon Jan 14 04:09:03 2008 +0000 @@ -48,6 +48,7 @@ gboolean bicon_sent_request; YahooPresenceVisibility presence; int protocol; /* 1=LCS, 2=MSN*/ + long int version_id; } YahooFriend; YahooFriend *yahoo_friend_find(PurpleConnection *gc, const char *name);
--- a/libpurple/protocols/yahoo/yahoo_packet.h Mon Jan 14 04:04:08 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo_packet.h Mon Jan 14 04:09:03 2008 +0000 @@ -99,12 +99,12 @@ YAHOO_SERVICE_VERIFY_ID_EXISTS = 0xc8, YAHOO_SERVICE_AUDIBLE = 0xd0, YAHOO_SERVICE_AUTH_REQ_15 = 0xd6, - YAHOO_SERVICE_Y7_FILETRANSFER = 0xdc, - YAHOO_SERVICE_Y7_FILETRANSFER_INFO = 0xdd, - YAHOO_SERVICE_Y7_FILETRANSFER_ACCEPT = 0xde, YAHOO_SERVICE_CHGRP_15 = 0xe7, YAHOO_SERVICE_STATUS_15 = 0xf0, YAHOO_SERVICE_LIST_15 = 0xf1, + YAHOO_SERVICE_FILETRANS_15 = 0xdc, + YAHOO_SERVICE_FILETRANS_INFO_15 = 0xdd, + YAHOO_SERVICE_FILETRANS_ACC_15 = 0xde, YAHOO_SERVICE_WEBLOGIN = 0x0226, YAHOO_SERVICE_SMS_MSG = 0x02ea };
--- a/libpurple/protocols/yahoo/yahoochat.c Mon Jan 14 04:04:08 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoochat.c Mon Jan 14 04:09:03 2008 +0000 @@ -1461,28 +1461,30 @@ PurpleRoomlist *yahoo_roomlist_get_list(PurpleConnection *gc) { - struct yahoo_roomlist *yrl; + PurpleAccount *account; PurpleRoomlist *rl; - const char *rll; + PurpleRoomlistField *f; + GList *fields = NULL; + struct yahoo_roomlist *yrl; + const char *rll, *rlurl; char *url; - GList *fields = NULL; - PurpleRoomlistField *f; - rll = purple_account_get_string(purple_connection_get_account(gc), - "room_list_locale", YAHOO_ROOMLIST_LOCALE); + account = purple_connection_get_account(gc); - if (rll != NULL && *rll != '\0') { - url = g_strdup_printf("%s?chatcat=0&intl=%s", - purple_account_get_string(purple_connection_get_account(gc), - "room_list", YAHOO_ROOMLIST_URL), rll); - } else { - url = g_strdup_printf("%s?chatcat=0", - purple_account_get_string(purple_connection_get_account(gc), - "room_list", YAHOO_ROOMLIST_URL)); + /* for Yahoo Japan, it appears there is only one valid URL and locale */ + if(purple_account_get_bool(account, "yahoojp", FALSE)) { + rll = YAHOOJP_ROOMLIST_LOCALE; + rlurl = YAHOOJP_ROOMLIST_URL; + } + else { /* but for the rest of the world that isn't the case */ + rll = purple_account_get_string(account, "room_list_locale", YAHOO_ROOMLIST_LOCALE); + rlurl = purple_account_get_string(account, "room_list", YAHOO_ROOMLIST_URL); } + url = g_strdup_printf("%s?chatcat=0&intl=%s", rlurl, rll); + yrl = g_new0(struct yahoo_roomlist, 1); - rl = purple_roomlist_new(purple_connection_get_account(gc)); + rl = purple_roomlist_new(account); yrl->list = rl; purple_url_parse(url, &(yrl->host), NULL, &(yrl->path), NULL, NULL); @@ -1508,7 +1510,7 @@ purple_roomlist_set_fields(rl, fields); - if (purple_proxy_connect(NULL, purple_connection_get_account(gc), yrl->host, 80, + if (purple_proxy_connect(NULL, account, yrl->host, 80, yahoo_roomlist_got_connected, yrl) == NULL) { purple_notify_error(gc, NULL, _("Connection problem"), _("Unable to fetch room list."));
--- a/libpurple/prpl.c Mon Jan 14 04:04:08 2008 +0000 +++ b/libpurple/prpl.c Mon Jan 14 04:09:03 2008 +0000 @@ -29,6 +29,107 @@ #include "util.h" /**************************************************************************/ +/** @name Attention Type API */ +/**************************************************************************/ +PurpleAttentionType * +purple_attention_type_new(const char *ulname, const char *name, + const char *inc_desc, const char *out_desc) +{ + PurpleAttentionType *attn = g_new0(PurpleAttentionType, 1); + + purple_attention_type_set_name(attn, name); + purple_attention_type_set_incoming_desc(attn, inc_desc); + purple_attention_type_set_outgoing_desc(attn, out_desc); + purple_attention_type_set_unlocalized_name(attn, ulname); + + return attn; +} + + +void +purple_attention_type_set_name(PurpleAttentionType *type, const char *name) +{ + g_return_if_fail(type != NULL); + + type->name = name; +} + +void +purple_attention_type_set_incoming_desc(PurpleAttentionType *type, const char *desc) +{ + g_return_if_fail(type != NULL); + + type->incoming_description = desc; +} + +void +purple_attention_type_set_outgoing_desc(PurpleAttentionType *type, const char *desc) +{ + g_return_if_fail(type != NULL); + + type->outgoing_description = desc; +} + +void +purple_attention_type_set_icon_name(PurpleAttentionType *type, const char *name) +{ + g_return_if_fail(type != NULL); + + type->icon_name = name; +} + +void +purple_attention_type_set_unlocalized_name(PurpleAttentionType *type, const char *ulname) +{ + g_return_if_fail(type != NULL); + + type->unlocalized_name = ulname; +} + +const char * +purple_attention_type_get_name(PurpleAttentionType *type) +{ + g_return_val_if_fail(type != NULL, NULL); + + return type->name; +} + +const char * +purple_attention_type_get_incoming_desc(PurpleAttentionType *type) +{ + g_return_val_if_fail(type != NULL, NULL); + + return type->incoming_description; +} + +const char * +purple_attention_type_get_outgoing_desc(PurpleAttentionType *type) +{ + g_return_val_if_fail(type != NULL, NULL); + + return type->outgoing_description; +} + +const char * +purple_attention_type_get_icon_name(PurpleAttentionType *type) +{ + g_return_val_if_fail(type != NULL, NULL); + + if(type->icon_name == NULL || *(type->icon_name) == '\0') + return NULL; + + return type->icon_name; +} + +const char * +purple_attention_type_get_unlocalized_name(PurpleAttentionType *type) +{ + g_return_val_if_fail(type != NULL, NULL); + + return type->unlocalized_name; +} + +/**************************************************************************/ /** @name Protocol Plugin API */ /**************************************************************************/ void
--- a/libpurple/prpl.h Mon Jan 14 04:04:08 2008 +0000 +++ b/libpurple/prpl.h Mon Jan 14 04:09:03 2008 +0000 @@ -99,9 +99,9 @@ const char *incoming_description; /**< Shown when sent */ const char *outgoing_description; /**< Shown when receied */ const char *icon_name; /**< Icon to display (optional) */ + const char *unlocalized_name; /**< Unlocalized name for UIs needing it */ /* Reserved fields for future purposes */ - gpointer _reserved1; gpointer _reserved2; gpointer _reserved3; gpointer _reserved4; @@ -412,6 +412,127 @@ #endif /**************************************************************************/ +/** @name Attention Type API */ +/**************************************************************************/ +/*@{*/ + +/** + * Creates a new #PurpleAttentionType object and sets its mandatory parameters. + * + * @param ulname A non-localized string that can be used by UIs in need of such + * non-localized strings. This should be the same as @a name, + * without localization. + * @param name A localized string that the UI may display for the event. This + * should be the same string as @a ulname, with localization. + * @param inc_desc A localized description shown when the event is received. + * @param out_desc A localized description shown when the event is sent. + * @return A pointer to the new object. + * @since 2.4.0 + */ +PurpleAttentionType *purple_attention_type_new(const char *ulname, const char *name, + const char *inc_desc, const char *out_desc); + +/** + * Sets the displayed name of the attention-demanding event. + * + * @param type The attention type. + * @param name The localized name that will be displayed by UIs. This should be + * the same string given as the unlocalized name, but with + * localization. + * @since 2.4.0 + */ +void purple_attention_type_set_name(PurpleAttentionType *type, const char *name); + +/** + * Sets the description of the attention-demanding event shown in conversations + * when the event is received. + * + * @param type The attention type. + * @param desc The localized description for incoming events. + * @since 2.4.0 + */ +void purple_attention_type_set_incoming_desc(PurpleAttentionType *type, const char *desc); + +/** + * Sets the description of the attention-demanding event shown in conversations + * when the event is sent. + * + * @param type The attention type. + * @param desc The localized description for outgoing events. + * @since 2.4.0 + */ +void purple_attention_type_set_outgoing_desc(PurpleAttentionType *type, const char *desc); + +/** + * Sets the name of the icon to display for the attention event; this is optional. + * + * @param type The attention type. + * @param name The icon's name. + * @note Icons are optional for attention events. + * @since 2.4.0 + */ +void purple_attention_type_set_icon_name(PurpleAttentionType *type, const char *name); + +/** + * Sets the unlocalized name of the attention event; some UIs may need this, + * thus it is required. + * + * @param type The attention type. + * @param ulname The unlocalized name. This should be the same string given as + * the localized name, but without localization. + * @since 2.4.0 + */ +void purple_attention_type_set_unlocalized_name(PurpleAttentionType *type, const char *ulname); + +/** + * Get the attention type's name as displayed by the UI. + * + * @param type The attention type. + * @return The name. + * @since 2.4.0 + */ +const char *purple_attention_type_get_name(PurpleAttentionType *type); + +/** + * Get the attention type's description shown when the event is received. + * + * @param type The attention type. + * @return The description. + * @since 2.4.0 + */ +const char *purple_attention_type_get_incoming_desc(PurpleAttentionType *type); + +/** + * Get the attention type's description shown when the event is sent. + * + * @param type The attention type. + * @return The description. + * @since 2.4.0 + */ +const char *purple_attention_type_get_outgoing_desc(PurpleAttentionType *type); + +/** + * Get the attention type's icon name. + * + * @param type The attention type. + * @return The icon name or @c NULL if unset/empty. + * @note Icons are optional for attention events. + * @since 2.4.0 + */ +const char *purple_attention_type_get_icon_name(PurpleAttentionType *type); + +/** + * Get the attention type's unlocalized name; this is useful for some UIs. + * + * @param type The attention type + * @return The unlocalized name. + * @since 2.4.0 + */ +const char *purple_attention_type_get_unlocalized_name(PurpleAttentionType *type); + +/*@}*/ + +/**************************************************************************/ /** @name Protocol Plugin API */ /**************************************************************************/ /*@{*/
--- a/libpurple/util.c Mon Jan 14 04:04:08 2008 +0000 +++ b/libpurple/util.c Mon Jan 14 04:09:03 2008 +0000 @@ -4629,6 +4629,15 @@ #endif /* !_WIN32 */ } +static void +set_status_with_attrs(PurpleStatus *status, ...) +{ + va_list args; + va_start(args, status); + purple_status_set_active_with_attrs(status, TRUE, args); + va_end(args); +} + void purple_util_set_current_song(const char *title, const char *artist, const char *album) { GList *list = purple_accounts_get_all(); @@ -4644,10 +4653,11 @@ if (!tune) continue; if (title) { - purple_status_set_active(tune, TRUE); - purple_status_set_attr_string(tune, PURPLE_TUNE_TITLE, title); - purple_status_set_attr_string(tune, PURPLE_TUNE_ARTIST, artist); - purple_status_set_attr_string(tune, PURPLE_TUNE_ALBUM, album); + set_status_with_attrs(tune, + PURPLE_TUNE_TITLE, title, + PURPLE_TUNE_ARTIST, artist, + PURPLE_TUNE_ALBUM, album, + NULL); } else { purple_status_set_active(tune, FALSE); } @@ -4659,7 +4669,7 @@ GString *string; char *esc; - if (!title) + if (!title || !*title) return NULL; esc = g_markup_escape_text(title, -1); @@ -4667,13 +4677,13 @@ g_string_append_printf(string, "%s", esc); g_free(esc); - if (artist) { + if (artist && *artist) { esc = g_markup_escape_text(artist, -1); g_string_append_printf(string, _(" - %s"), esc); g_free(esc); } - if (album) { + if (album && *album) { esc = g_markup_escape_text(album, -1); g_string_append_printf(string, _(" (%s)"), esc); g_free(esc);
--- a/pidgin/gtkaccount.c Mon Jan 14 04:04:08 2008 +0000 +++ b/pidgin/gtkaccount.c Mon Jan 14 04:09:03 2008 +0000 @@ -2177,6 +2177,7 @@ treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model)); dialog->treeview = treeview; gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE); + g_object_unref(G_OBJECT(dialog->model)); sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE);
--- a/pidgin/gtkblist.c Mon Jan 14 04:04:08 2008 +0000 +++ b/pidgin/gtkblist.c Mon Jan 14 04:09:03 2008 +0000 @@ -937,7 +937,6 @@ pidgin_blist_joinchat_show(void) { GtkWidget *hbox, *vbox; - GtkWidget *rowbox; GtkWidget *label; PidginBuddyList *gtkblist; GtkWidget *img = NULL; @@ -981,7 +980,6 @@ data->account_menu = pidgin_account_option_menu_new(NULL, FALSE, G_CALLBACK(joinchat_select_account_cb), chat_account_filter_func, data); - gtk_box_pack_start(GTK_BOX(rowbox), data->account_menu, TRUE, TRUE, 0); pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Account:"), data->sg, data->account_menu, TRUE, NULL); @@ -6071,6 +6069,7 @@ gtkblist->timeout = 0; gtkblist->drag_timeout = 0; gtkblist->window = gtkblist->vbox = gtkblist->treeview = NULL; + g_object_unref(G_OBJECT(gtkblist->treemodel)); gtkblist->treemodel = NULL; g_object_unref(G_OBJECT(gtkblist->ift)); g_object_unref(G_OBJECT(gtkblist->empty_avatar));
--- a/pidgin/gtkcertmgr.c Mon Jan 14 04:04:08 2008 +0000 +++ b/pidgin/gtkcertmgr.c Mon Jan 14 04:09:03 2008 +0000 @@ -422,6 +422,7 @@ tpm_dat->listview = listview = GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(store))); + g_object_unref(G_OBJECT(store)); { GtkCellRenderer *renderer;
--- a/pidgin/gtkimhtml.c Mon Jan 14 04:04:08 2008 +0000 +++ b/pidgin/gtkimhtml.c Mon Jan 14 04:09:03 2008 +0000 @@ -1455,6 +1455,9 @@ gtk_text_buffer_create_tag(imhtml->text_buffer, "SUP", "rise", 5000, NULL); gtk_text_buffer_create_tag(imhtml->text_buffer, "PRE", "family", "Monospace", NULL); gtk_text_buffer_create_tag(imhtml->text_buffer, "search", "background", "#22ff00", "weight", "bold", NULL); +#if GTK_CHECK_VERSION(2,8,0) + gtk_text_buffer_create_tag(imhtml->text_buffer, "comment", "invisible", FALSE, NULL); +#endif /* When hovering over a link, we show the hand cursor--elsewhere we show the plain ol' pointer cursor */ imhtml->hand_cursor = gdk_cursor_new (GDK_HAND2); @@ -2981,10 +2984,15 @@ gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); +#if GTK_CHECK_VERSION(2,8,0) + wpos = g_snprintf (ws, len, "%s", tag); + gtk_text_buffer_insert_with_tags_by_name(imhtml->text_buffer, iter, ws, wpos, "comment", NULL); +#else if (imhtml->show_comments && !(options & GTK_IMHTML_NO_COMMENTS)) { wpos = g_snprintf (ws, len, "%s", tag); gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); } +#endif ws[0] = '\0'; wpos = 0; /* NEW_BIT (NEW_COMMENT_BIT); */ @@ -3130,6 +3138,12 @@ void gtk_imhtml_show_comments (GtkIMHtml *imhtml, gboolean show) { +#if GTK_CHECK_VERSION(2,8,0) + GtkTextTag *tag; + tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), "comment"); + if (tag) + g_object_set(G_OBJECT(tag), "invisible", !show, NULL); +#endif imhtml->show_comments = show; }
--- a/pidgin/gtkimhtmltoolbar.c Mon Jan 14 04:04:08 2008 +0000 +++ b/pidgin/gtkimhtmltoolbar.c Mon Jan 14 04:09:03 2008 +0000 @@ -1312,6 +1312,7 @@ gtk_box_pack_start(GTK_BOX(hbox), box, FALSE, FALSE, 0); g_object_set_data(G_OBJECT(hbox), "lean-view", box); + gtk_widget_show(box); purple_prefs_connect_callback(toolbar, PIDGIN_PREFS_ROOT "/conversations/toolbar/wide", imhtmltoolbar_view_pref_changed, toolbar);
--- a/pidgin/gtklog.c Mon Jan 14 04:04:08 2008 +0000 +++ b/pidgin/gtklog.c Mon Jan 14 04:09:03 2008 +0000 @@ -614,6 +614,7 @@ gtk_paned_add1(GTK_PANED(pane), sw); lv->treestore = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_POINTER); lv->treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (lv->treestore)); + g_object_unref(G_OBJECT(lv->treestore)); rend = gtk_cell_renderer_text_new(); col = gtk_tree_view_column_new_with_attributes ("time", rend, "markup", 0, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW(lv->treeview), col);
--- a/pidgin/gtknotify.c Mon Jan 14 04:04:08 2008 +0000 +++ b/pidgin/gtknotify.c Mon Jan 14 04:09:03 2008 +0000 @@ -379,6 +379,7 @@ mail_dialog->treemodel = gtk_tree_store_new(COLUMNS_PIDGIN_MAIL, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER); mail_dialog->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(mail_dialog->treemodel)); + g_object_unref(G_OBJECT(mail_dialog->treemodel)); gtk_tree_view_set_search_column(GTK_TREE_VIEW(mail_dialog->treeview), PIDGIN_MAIL_TEXT); gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(mail_dialog->treeview), pidgin_tree_view_search_equal_func, NULL, NULL); @@ -818,6 +819,7 @@ /* Setup the treeview */ treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model)); + g_object_unref(G_OBJECT(model)); gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE); gtk_widget_set_size_request(treeview, 500, 400); gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)),
--- a/pidgin/gtkpounce.c Mon Jan 14 04:04:08 2008 +0000 +++ b/pidgin/gtkpounce.c Mon Jan 14 04:09:03 2008 +0000 @@ -1237,6 +1237,7 @@ /* Create the treeview */ treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model)); + g_object_unref(G_OBJECT(dialog->model)); dialog->treeview = treeview; gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
--- a/pidgin/gtkprefs.c Mon Jan 14 04:04:08 2008 +0000 +++ b/pidgin/gtkprefs.c Mon Jan 14 04:09:03 2008 +0000 @@ -1465,15 +1465,15 @@ } entry = gtk_entry_new(); - if (strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/browsers/browser"), "custom")) - gtk_widget_set_sensitive(hbox, FALSE); - purple_prefs_connect_callback(prefs, PIDGIN_PREFS_ROOT "/browsers/browser", - browser_changed2_cb, hbox); gtk_entry_set_text(GTK_ENTRY(entry), purple_prefs_get_path(PIDGIN_PREFS_ROOT "/browsers/command")); g_signal_connect(G_OBJECT(entry), "focus-out-event", G_CALLBACK(manual_browser_set), NULL); - pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Manual:\n(%s for URL)"), sg, entry, TRUE, NULL); + hbox = pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Manual:\n(%s for URL)"), sg, entry, TRUE, NULL); + if (strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/browsers/browser"), "custom")) + gtk_widget_set_sensitive(hbox, FALSE); + purple_prefs_connect_callback(prefs, PIDGIN_PREFS_ROOT "/browsers/browser", + browser_changed2_cb, hbox); gtk_widget_show_all(ret); g_object_unref(sg);
--- a/pidgin/gtkprivacy.c Mon Jan 14 04:04:08 2008 +0000 +++ b/pidgin/gtkprivacy.c Mon Jan 14 04:09:03 2008 +0000 @@ -474,6 +474,8 @@ if (privacy_dialog == NULL) return; + g_object_unref(G_OBJECT(privacy_dialog->allow_store)); + g_object_unref(G_OBJECT(privacy_dialog->block_store)); g_free(privacy_dialog); privacy_dialog = NULL; }
--- a/pidgin/gtkrequest.c Mon Jan 14 04:04:08 2008 +0000 +++ b/pidgin/gtkrequest.c Mon Jan 14 04:09:03 2008 +0000 @@ -1007,6 +1007,7 @@ /* Create the tree view */ treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); + g_object_unref(G_OBJECT(store)); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE); sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
--- a/pidgin/gtksavedstatuses.c Mon Jan 14 04:04:08 2008 +0000 +++ b/pidgin/gtksavedstatuses.c Mon Jan 14 04:09:03 2008 +0000 @@ -669,6 +669,7 @@ purple_request_close_with_handle(status_window); purple_notify_close_with_handle(status_window); purple_signals_disconnect_by_handle(status_window); + g_object_unref(G_OBJECT(status_window->model)); g_free(status_window); status_window = NULL; } @@ -723,6 +724,7 @@ status_editor_remove_dialog(dialog); g_free(dialog->original_title); + g_object_unref(G_OBJECT(dialog->model)); g_free(dialog); return FALSE;
--- a/pidgin/gtkstatusbox.c Mon Jan 14 04:04:08 2008 +0000 +++ b/pidgin/gtkstatusbox.c Mon Jan 14 04:09:03 2008 +0000 @@ -515,16 +515,10 @@ purple_signals_disconnect_by_handle(statusbox); purple_prefs_disconnect_by_handle(statusbox); - gdk_cursor_unref(statusbox->hand_cursor); - gdk_cursor_unref(statusbox->arrow_cursor); + destroy_icon_box(statusbox); - purple_imgstore_unref(statusbox->buddy_icon_img); - g_object_unref(G_OBJECT(statusbox->buddy_icon)); - g_object_unref(G_OBJECT(statusbox->buddy_icon_hover)); - - if (statusbox->buddy_icon_sel) - gtk_widget_destroy(statusbox->buddy_icon_sel); - + g_object_unref(G_OBJECT(statusbox->store)); + g_object_unref(G_OBJECT(statusbox->dropdown_store)); G_OBJECT_CLASS(parent_class)->finalize(obj); }