# HG changeset patch # User Ethan Blanton # Date 1071074903 0 # Node ID ee32e030c9be3d9d63a8a13f743df74d5077dc74 # Parent 5ba07997ade3bd05cf2cf6daef26d37dc57178c5 [gaim-migrate @ 8479] marv asserts that these character set conversions are more correct than the previous yahoo conversions, which assumed that pretty much everything was UTF-8. I believe him. committer: Tailor Script diff -r 5ba07997ade3 -r ee32e030c9be src/protocols/yahoo/util.c --- a/src/protocols/yahoo/util.c Wed Dec 10 07:37:13 2003 +0000 +++ b/src/protocols/yahoo/util.c Wed Dec 10 16:48:23 2003 +0000 @@ -26,9 +26,68 @@ #include "prpl.h" #include "debug.h" +#include "yahoo.h" #include +/** + * Encode some text to send to the yahoo server. + * + * @param gc The connection handle. + * @param str The null terminated utf8 string to encode. + * @param utf8 If not @c NULL, whether utf8 is okay or not. + * Even if it is okay, we may not use it. If we + * used it, we set this to @c TRUE, else to + * @c FALSE. If @c NULL, false is assumed, and + * it is not dereferenced. + * @return The g_malloced string in the appropriate encoding. + */ +char *yahoo_string_encode(GaimConnection *gc, const char *str, gboolean *utf8) +{ + char *ret; + char *to_codeset; + + if (utf8 && *utf8) /* FIXME: maybe don't use utf8 if it'll fit in latin1 */ + return g_strdup(str); + + to_codeset = "ISO-8859-1"; + + ret = g_convert_with_fallback(str, strlen(str), to_codeset, "UTF-8", NULL, NULL, NULL, NULL); + if (ret) + return ret; + else + return g_strdup(""); +} + +/** + * Decode some text received from the server. + * + * @param gc The gc handle. + * @param str The null terminated string to decode. + * @param utf8 Did the server tell us it was supposed to be utf8? + * @return The decoded, utf-8 string, which must be g_free()'d. + */ +char *yahoo_string_decode(GaimConnection *gc, const char *str, gboolean utf8) +{ + char *ret; + char *from_codeset; + + if (utf8) { + if (g_utf8_validate(str, -1, NULL)) + return g_strdup(str); + } + + from_codeset = "ISO-8859-1"; + + ret = g_convert_with_fallback(str, strlen(str), "UTF-8", from_codeset, NULL, NULL, NULL, NULL); + + if (ret) + return ret; + else + return g_strdup(""); +} + + /* * I found these on some website but i don't know that they actually diff -r 5ba07997ade3 -r ee32e030c9be src/protocols/yahoo/yahoo.c --- a/src/protocols/yahoo/yahoo.c Wed Dec 10 07:37:13 2003 +0000 +++ b/src/protocols/yahoo/yahoo.c Wed Dec 10 16:48:23 2003 +0000 @@ -51,13 +51,6 @@ /* #define YAHOO_DEBUG */ -#define USEROPT_MAIL 0 - -#define YAHOO_PAGER_HOST "scs.yahoo.com" -#define YAHOO_PAGER_PORT 5050 -#define YAHOO_PROFILE_URL "http://profiles.yahoo.com/" - - static void yahoo_add_buddy(GaimConnection *gc, const char *who, GaimGroup *); static struct yahoo_friend *yahoo_friend_new(void) @@ -361,7 +354,7 @@ if (f) { if (f->msg) g_free(f->msg); - f->msg = g_strdup(pair->value); + f->msg = yahoo_string_decode(gc, pair->value, FALSE); } break; case 11: /* this is the buddy's session id */ @@ -407,7 +400,11 @@ } break; case 16: /* Custom error message */ - gaim_notify_error(gc, NULL, pair->value, NULL); + { + char *tmp = yahoo_string_decode(gc, pair->value, TRUE); + gaim_notify_error(gc, NULL, tmp, NULL); + g_free(tmp); + } break; default: gaim_debug(GAIM_DEBUG_ERROR, "yahoo", @@ -533,6 +530,7 @@ char **split; char **buddies; char **tmp, **bud, *norm_bud; + char *grp = NULL; if (pkt->id) yd->session_id = pkt->id; @@ -575,6 +573,7 @@ g_strfreev(split); continue; } + grp = yahoo_string_decode(gc, split[0], FALSE); buddies = g_strsplit(split[1], ",", -1); for (bud = buddies; bud && *bud; bud++) { norm_bud = g_strdup(gaim_normalize(account, *bud)); @@ -582,9 +581,9 @@ f = yahoo_friend_new(); g_hash_table_insert(yd->friends, g_strdup(norm_bud), f); } - if (!(b = gaim_find_buddy(account, norm_bud))) { - if (!(g = gaim_find_group(split[0]))) { - g = gaim_group_new(split[0]); + if (!(b = gaim_find_buddy(account, norm_bud))) { + if (!(g = gaim_find_group(grp))) { + g = gaim_group_new(grp); gaim_blist_add_group(g, NULL); } b = gaim_buddy_new(account, norm_bud, NULL); @@ -592,11 +591,12 @@ export = TRUE; } - yahoo_do_group_check(account, ht, norm_bud, split[0], &export); + yahoo_do_group_check(account, ht, norm_bud, grp, &export); g_free(norm_bud); } g_strfreev(buddies); g_strfreev(split); + g_free(grp); } g_strfreev(lines); @@ -686,31 +686,38 @@ } } + +struct _yahoo_im { + char *from; + int time; + int utf8; + char *msg; +}; + static void yahoo_process_message(GaimConnection *gc, struct yahoo_packet *pkt) { - char *msg = NULL; - char *from = NULL; - time_t tm = time(NULL); GSList *l = pkt->hash; + GSList *list = NULL; + struct _yahoo_im *im = NULL; if (pkt->status <= 1 || pkt->status == 5) { while (l) { struct yahoo_pair *pair = l->data; - if (pair->key == 4) - from = pair->value; + if (pair->key == 4) { + im = g_new0(struct _yahoo_im, 1); + list = g_slist_append(list, im); + im->from = pair->value; + im->time = time(NULL); + } + if (pair->key == 97) + if (im) + im->utf8 = strtol(pair->value, NULL, 10); if (pair->key == 15) - tm = strtol(pair->value, NULL, 10); + if (im) + im->time = strtol(pair->value, NULL, 10); if (pair->key == 14) { - char *m; - - msg = pair->value; - - gaim_str_strip_cr(msg); - m = yahoo_codes_to_html(msg); - serv_got_im(gc, from, m, 0, tm); - g_free(m); - - tm = time(NULL); + if (im) + im->msg = pair->value; } l = l->next; } @@ -718,12 +725,31 @@ gaim_notify_error(gc, NULL, _("Your Yahoo! message did not get sent."), NULL); } + + for (l = list; l; l = l->next) { + char *m, *m2; + im = l->data; + + if (!im->from || !im->msg) { + g_free(im); + continue; + } + + m = yahoo_string_decode(gc, im->msg, im->utf8); + gaim_str_strip_cr(m); + m2 = yahoo_codes_to_html(m); + g_free(m); + serv_got_im(gc, im->from, m2, 0, im->time); + g_free(m2); + g_free(im); + } + g_slist_free(list); } static void yahoo_buddy_added_us(GaimConnection *gc, struct yahoo_packet *pkt) { char *id = NULL; char *who = NULL; - char *msg = NULL; + char *msg = NULL, *tmpmsg = NULL; GSList *l = pkt->hash; while (l) { @@ -745,8 +771,13 @@ l = l->next; } - if (id) - gaim_account_notify_added(gc->account, id, who, NULL, msg); + if (id) { + if (msg) + tmpmsg = yahoo_string_decode(gc, msg, FALSE); + gaim_account_notify_added(gc->account, id, who, NULL, tmpmsg); + if (tmpmsg) + g_free(tmpmsg); + } } static void yahoo_buddy_denied_our_add(GaimConnection *gc, struct yahoo_packet *pkt) @@ -772,11 +803,15 @@ } if (who) { + char *msg2; buf = g_string_sized_new(0); - if (!msg) + if (!msg) { g_string_printf(buf, _("%s has (retroactively) denied your request to add them to your list."), who); - else - g_string_printf(buf, _("%s has (retroactively) denied your request to add them to your list for the following reason: %s."), who, msg); + } else { + msg2 = yahoo_string_decode(gc, msg, FALSE); + g_string_printf(buf, _("%s has (retroactively) denied your request to add them to your list for the following reason: %s."), who, msg2); + g_free(msg2); + } gaim_notify_info(gc, NULL, _("Add buddy rejected"), buf->str); g_string_free(buf, TRUE); g_hash_table_remove(yd->friends, who); @@ -1551,6 +1586,7 @@ int err = 0; char *who = NULL; char *group = NULL; + char *decoded_group; char *buf; struct yahoo_friend *f; struct yahoo_data *yd = gc->proto_data; @@ -1588,10 +1624,12 @@ return; } + decoded_group = yahoo_string_decode(gc, group, FALSE); buf = g_strdup_printf(_("Could not add buddy %s to group %s to the server list on account %s."), - who, group, gaim_connection_get_display_name(gc)); + who, decoded_group, gaim_connection_get_display_name(gc)); gaim_notify_error(gc, NULL, _("Could not add buddy to server list"), buf); g_free(buf); + g_free(decoded_group); } static void yahoo_packet_process(GaimConnection *gc, struct yahoo_packet *pkt) @@ -1981,12 +2019,16 @@ yd->conf_id = 2; #ifndef YAHOO_WEBMESSENGER - if (gaim_proxy_connect(account, gaim_account_get_string(account, "server", YAHOO_PAGER_HOST), - gaim_account_get_int(account, "port", YAHOO_PAGER_PORT), - yahoo_got_connected, gc) != 0) { + + if (gaim_proxy_connect(account, + gaim_account_get_string(account, "server", YAHOO_PAGER_HOST), + gaim_account_get_int(account, "port", YAHOO_PAGER_PORT), + yahoo_got_connected, gc) != 0) + { gaim_connection_error(gc, _("Connection problem")); return; } + #else gaim_url_fetch(WEBMESSENGER_URL, TRUE, "Gaim/" VERSION, FALSE, yahoo_login_page_cb, gc); @@ -2314,17 +2356,24 @@ struct yahoo_data *yd = gc->proto_data; struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE, YAHOO_STATUS_OFFLINE, 0); char *msg = yahoo_html_to_codes(what); + char *msg2; + gboolean utf8 = TRUE; + + msg2 = yahoo_string_encode(gc, msg, &utf8); yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc)); yahoo_packet_hash(pkt, 5, who); - yahoo_packet_hash(pkt, 14, msg); - yahoo_packet_hash(pkt, 97, "1"); + if (utf8) + yahoo_packet_hash(pkt, 97, "1"); + yahoo_packet_hash(pkt, 14, msg2); + yahoo_send_packet(yd, pkt); yahoo_packet_free(pkt); g_free(msg); + g_free(msg2); return 1; } @@ -2353,6 +2402,7 @@ struct yahoo_packet *pkt; int service; char s[4]; + char *conv_msg = NULL; if (gc->away) { g_free(gc->away); @@ -2408,8 +2458,10 @@ g_snprintf(s, sizeof(s), "%d", yd->current_status); yahoo_packet_hash(pkt, 10, s); - if ((yd->current_status == YAHOO_STATUS_CUSTOM) && gc->away) - yahoo_packet_hash(pkt, 19, gc->away); + if ((yd->current_status == YAHOO_STATUS_CUSTOM) && gc->away) { + conv_msg = yahoo_string_encode(gc, gc->away, NULL); + yahoo_packet_hash(pkt, 19, conv_msg); + } if ((yd->current_status != YAHOO_STATUS_AVAILABLE) && (yd->current_status != YAHOO_STATUS_IDLE)) { @@ -2421,12 +2473,15 @@ yahoo_send_packet(yd, pkt); yahoo_packet_free(pkt); + if (conv_msg) + g_free(conv_msg); } static void yahoo_set_idle(GaimConnection *gc, int idle) { struct yahoo_data *yd = gc->proto_data; struct yahoo_packet *pkt = NULL; + char *msg = NULL; if (idle && yd->current_status == YAHOO_STATUS_AVAILABLE) { pkt = yahoo_packet_new(YAHOO_SERVICE_ISAWAY, YAHOO_STATUS_AVAILABLE, 0); @@ -2443,7 +2498,8 @@ g_snprintf(buf, sizeof(buf), "%d", yd->current_status); yahoo_packet_hash(pkt, 10, buf); if (gc->away && yd->current_status == YAHOO_STATUS_CUSTOM) { - yahoo_packet_hash(pkt, 19, gc->away); + msg = yahoo_string_encode(gc, gc->away, NULL); + yahoo_packet_hash(pkt, 19, msg); if (idle) yahoo_packet_hash(pkt, 47, "2"); else @@ -2459,6 +2515,8 @@ yahoo_send_packet(yd, pkt); yahoo_packet_free(pkt); } + if (msg) + g_free(msg); } static GList *yahoo_away_states(GaimConnection *gc) @@ -2503,6 +2561,7 @@ struct yahoo_packet *pkt; GaimGroup *g; char *group = NULL; + char *grp2 = NULL; if (!yd->logged_in) return; @@ -2517,13 +2576,15 @@ group = "Buddies"; } + grp2 = yahoo_string_encode(gc, group, NULL); pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YAHOO_STATUS_AVAILABLE, 0); yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc)); yahoo_packet_hash(pkt, 7, who); - yahoo_packet_hash(pkt, 65, group); + yahoo_packet_hash(pkt, 65, grp2); yahoo_packet_hash(pkt, 14, ""); yahoo_send_packet(yd, pkt); yahoo_packet_free(pkt); + g_free(grp2); } static void yahoo_remove_buddy(GaimConnection *gc, const char *who, const char *group) @@ -2534,6 +2595,7 @@ GSList *buddies, *l; GaimGroup *g; gboolean remove = TRUE; + char *cg; if (!(f = g_hash_table_lookup(yd->friends, who))) return; @@ -2552,12 +2614,14 @@ if (remove) g_hash_table_remove(yd->friends, who); + cg = yahoo_string_encode(gc, group, NULL); pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YAHOO_STATUS_AVAILABLE, 0); yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc)); yahoo_packet_hash(pkt, 7, who); - yahoo_packet_hash(pkt, 65, group); + yahoo_packet_hash(pkt, 65, cg); yahoo_send_packet(yd, pkt); yahoo_packet_free(pkt); + g_free(cg); } static void yahoo_add_deny(GaimConnection *gc, const char *who) { @@ -2884,6 +2948,7 @@ { struct yahoo_data *yd = gc->proto_data; struct yahoo_packet *pkt; + char *gpn, *gpo; /* Step 0: If they aren't on the server list anyway, * don't bother letting the server know. @@ -2891,11 +2956,23 @@ if (!g_hash_table_lookup(yd->friends, who)) return; + /* If old and new are the same, we would probably + * end up deleting the buddy, which would be bad. + * This might happen because of the charset conversation. + */ + gpn = yahoo_string_encode(gc, new_group, NULL); + gpo = yahoo_string_encode(gc, old_group, NULL); + if (!strcmp(gpn, gpo)) { + g_free(gpn); + g_free(gpo); + return; + } + /* Step 1: Add buddy to new group. */ pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YAHOO_STATUS_AVAILABLE, 0); yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc)); yahoo_packet_hash(pkt, 7, who); - yahoo_packet_hash(pkt, 65, new_group); + yahoo_packet_hash(pkt, 65, gpn); yahoo_packet_hash(pkt, 14, ""); yahoo_send_packet(yd, pkt); yahoo_packet_free(pkt); @@ -2904,9 +2981,11 @@ pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YAHOO_STATUS_AVAILABLE, 0); yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc)); yahoo_packet_hash(pkt, 7, who); - yahoo_packet_hash(pkt, 65, old_group); + yahoo_packet_hash(pkt, 65, gpo); yahoo_send_packet(yd, pkt); yahoo_packet_free(pkt); + g_free(gpn); + g_free(gpo); } static void yahoo_rename_group(GaimConnection *gc, const char *old_group, @@ -2914,13 +2993,24 @@ { struct yahoo_data *yd = gc->proto_data; struct yahoo_packet *pkt; + char *gpn, *gpo; + + gpn = yahoo_string_encode(gc, new_group, NULL); + gpo = yahoo_string_encode(gc, old_group, NULL); + if (!strcmp(gpn, gpo)) { + g_free(gpn); + g_free(gpo); + return; + } pkt = yahoo_packet_new(YAHOO_SERVICE_GROUPRENAME, YAHOO_STATUS_AVAILABLE, 0); yahoo_packet_hash(pkt, 1, gaim_connection_get_display_name(gc)); - yahoo_packet_hash(pkt, 65, old_group); - yahoo_packet_hash(pkt, 67, new_group); + yahoo_packet_hash(pkt, 65, gpo); + yahoo_packet_hash(pkt, 67, gpn); yahoo_send_packet(yd, pkt); yahoo_packet_free(pkt); + g_free(gpn); + g_free(gpo); } #if 0 @@ -3026,15 +3116,11 @@ { GaimAccountOption *option; - option = gaim_account_option_string_new(_("Pager host"), "server", - YAHOO_PAGER_HOST); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, - option); - - option = gaim_account_option_int_new(_("Pager port"), "port", - YAHOO_PAGER_PORT); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, - option); + option = gaim_account_option_string_new(_("Pager host"), "server", YAHOO_PAGER_HOST); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + + option = gaim_account_option_int_new(_("Pager port"), "port", YAHOO_PAGER_PORT); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); option = gaim_account_option_string_new(_("File transfer host"), "xfer_host", YAHOO_XFER_HOST); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); diff -r 5ba07997ade3 -r ee32e030c9be src/protocols/yahoo/yahoo.h --- a/src/protocols/yahoo/yahoo.h Wed Dec 10 07:37:13 2003 +0000 +++ b/src/protocols/yahoo/yahoo.h Wed Dec 10 16:48:23 2003 +0000 @@ -25,6 +25,9 @@ #include "prpl.h" +#define YAHOO_PAGER_HOST "scs.yahoo.com" +#define YAHOO_PAGER_PORT 5050 +#define YAHOO_PROFILE_URL "http://profiles.yahoo.com/" #define YAHOO_XFER_HOST "filetransfer.msg.yahoo.com" #define YAHOO_XFER_PORT 80 @@ -193,4 +196,28 @@ char *yahoo_codes_to_html(const char *x); char *yahoo_html_to_codes(const char *src); +/** + * Encode some text to send to the yahoo server. + * + * @param gc The connection handle. + * @param str The null terminated utf8 string to encode. + * @param utf8 If not @c NULL, whether utf8 is okay or not. + * Even if it is okay, we may not use it. If we + * used it, we set this to @c TRUE, else to + * @c FALSE. If @c NULL, false is assumed, and + * it is not dereferenced. + * @return The g_malloced string in the appropriate encoding. + */ +char *yahoo_string_encode(GaimConnection *gc, const char *str, gboolean *utf8); + +/** + * Decode some text received from the server. + * + * @param gc The gc handle. + * @param str The null terminated string to decode. + * @param utf8 Did the server tell us it was supposed to be utf8? + * @return The decoded, utf-8 string, which must be g_free()'d. + */ +char *yahoo_string_decode(GaimConnection *gc, const char *str, gboolean utf8); + #endif /* _YAHOO_H_ */ diff -r 5ba07997ade3 -r ee32e030c9be src/protocols/yahoo/yahoo_filexfer.c --- a/src/protocols/yahoo/yahoo_filexfer.c Wed Dec 10 07:37:13 2003 +0000 +++ b/src/protocols/yahoo/yahoo_filexfer.c Wed Dec 10 16:48:23 2003 +0000 @@ -189,9 +189,11 @@ struct yahoo_xfer_data *xfer_data; GaimConnection *gc; GaimAccount *account; + struct yahoo_data *yd; xfer_data = xfer->data; gc = xfer_data->gc; + yd = gc->proto_data; account = gaim_connection_get_account(gc); if (gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) { @@ -200,10 +202,9 @@ yahoo_sendfile_connected, xfer) == -1) { gaim_notify_error(gc, NULL, _("File Transfer Aborted"), - _("Unable to establish file descriptor.")); + _("Unable to establish file descriptor.")); gaim_xfer_cancel_remote(xfer); } - } else { xfer->fd = gaim_proxy_connect(account, xfer_data->host, xfer_data->port, yahoo_receivefile_connected, xfer); diff -r 5ba07997ade3 -r ee32e030c9be src/protocols/yahoo/yahoochat.c --- a/src/protocols/yahoo/yahoochat.c Wed Dec 10 07:37:13 2003 +0000 +++ b/src/protocols/yahoo/yahoochat.c Wed Dec 10 16:48:23 2003 +0000 @@ -130,7 +130,7 @@ case 1: /* us, but we already know who we are */ break; case 57: - room = pair->value; + room = yahoo_string_decode(gc, pair->value, FALSE); break; case 50: /* inviter */ who = pair->value; @@ -140,7 +140,7 @@ g_string_append_printf(members, "%s\n", pair->value); break; case 58: - msg = pair->value; + msg = yahoo_string_decode(gc, pair->value, FALSE); break; case 13: /* ? */ break; @@ -153,9 +153,9 @@ } components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); - g_hash_table_replace(components, g_strdup("room"), g_strdup(room)); + g_hash_table_replace(components, g_strdup("room"), room); if (msg) - g_hash_table_replace(components, g_strdup("topic"), g_strdup(msg)); + g_hash_table_replace(components, g_strdup("topic"), msg); g_hash_table_replace(components, g_strdup("type"), g_strdup("Conference")); if (members) { g_hash_table_replace(components, g_strdup("members"), g_strdup(members->str)); @@ -177,13 +177,13 @@ switch (pair->key) { case 57: - room = pair->value; + room = yahoo_string_decode(gc, pair->value, FALSE); break; case 54: who = pair->value; break; case 14: - msg = pair->value; + msg = yahoo_string_decode(gc, pair->value, FALSE); break; } } @@ -195,6 +195,9 @@ who, room, msg?msg:""); gaim_notify_info(gc, NULL, _("Invitation Rejected"), tmp); g_free(tmp); + g_free(room); + if (msg) + g_free(msg); } } @@ -210,7 +213,7 @@ switch (pair->key) { case 57: - room = pair->value; + room = yahoo_string_decode(gc, pair->value, FALSE); break; case 53: who = pair->value; @@ -222,6 +225,7 @@ c = yahoo_find_conference(gc, room); if (c) yahoo_chat_add_user(GAIM_CONV_CHAT(c), who, NULL); + g_free(room); } } @@ -237,7 +241,7 @@ switch (pair->key) { case 57: - room = pair->value; + room = yahoo_string_decode(gc, pair->value, FALSE); break; case 56: who = pair->value; @@ -249,6 +253,7 @@ c = yahoo_find_conference(gc, room); if (c) gaim_conv_chat_remove_user(GAIM_CONV_CHAT(c), who, NULL); + g_free(room); } } @@ -258,6 +263,8 @@ char *room = NULL; char *who = NULL; char *msg = NULL; + char *msg2; + int utf8 = 0; GaimConversation *c; for (l = pkt->hash; l; l = l->next) { @@ -265,7 +272,7 @@ switch (pair->key) { case 57: - room = pair->value; + room = yahoo_string_decode(gc, pair->value, FALSE); break; case 3: who = pair->value; @@ -273,18 +280,24 @@ case 14: msg = pair->value; break; + case 97: + utf8 = strtol(pair->value, NULL, 10); + break; } } if (room && who && msg) { + msg2 = yahoo_string_decode(gc, msg, utf8); c = yahoo_find_conference(gc, room); if (!c) return; - msg = yahoo_codes_to_html(msg); + msg = yahoo_codes_to_html(msg2); serv_got_chat_in(gc, gaim_conv_chat_get_id(GAIM_CONV_CHAT(c)), who, 0, msg, time(NULL)); g_free(msg); + g_free(msg2); } - + if (room) + g_free(room); } @@ -302,7 +315,7 @@ { struct yahoo_data *yd = (struct yahoo_data *) gc->proto_data; GSList *l; - + for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; @@ -311,7 +324,7 @@ gaim_connection_get_display_name(gc))) return; } - + if (pkt->status == 1) { yd->chat_online = 0; if (yd->in_chat) @@ -340,10 +353,10 @@ switch (pair->key) { case 104: - room = pair->value; + room = yahoo_string_decode(gc, pair->value, FALSE); break; case 105: - topic = pair->value; + topic = yahoo_string_decode(gc, pair->value, FALSE); break; case 128: someid = pair->value; @@ -404,6 +417,9 @@ } g_list_free(members); + g_free(room); + if (topic) + g_free(topic); } void yahoo_process_chat_exit(GaimConnection *gc, struct yahoo_packet *pkt) @@ -419,7 +435,7 @@ struct yahoo_pair *pair = l->data; if (pair->key == 104) - room = pair->value; + room = yahoo_string_decode(gc, pair->value, FALSE); if (pair->key == 109) who = pair->value; } @@ -431,12 +447,14 @@ gaim_conv_chat_remove_user(GAIM_CONV_CHAT(c), who, NULL); } + if (room) + g_free(room); } void yahoo_process_chat_message(GaimConnection *gc, struct yahoo_packet *pkt) { - char *room = NULL, *who = NULL, *msg = NULL; - int msgtype = 1; + char *room = NULL, *who = NULL, *msg = NULL, *msg2; + int msgtype = 1, utf8 = 0; GaimConversation *c = NULL; GSList *l; @@ -445,8 +463,11 @@ switch (pair->key) { + case 97: + utf8 = strtol(pair->value, NULL, 10); + break; case 104: - room = pair->value; + room = yahoo_string_decode(gc, pair->value, FALSE); break; case 109: who = pair->value; @@ -460,11 +481,11 @@ } } - if (!who) - return; c = gaim_find_chat(gc, YAHOO_CHAT_ID); - if (!c) { + if (!who || !c) { + if (room) + g_free(room); /* we still get messages after we part, funny that */ return; } @@ -473,7 +494,9 @@ gaim_debug(GAIM_DEBUG_MISC, "yahoo", "Got a message packet with no message.\nThis probably means something important, but we're ignoring it.\n"); return; } - msg = yahoo_codes_to_html(msg); + msg2 = yahoo_string_decode(gc, msg, utf8); + msg = yahoo_codes_to_html(msg2); + g_free(msg2); if (msgtype == 2 || msgtype == 3) { char *tmp; @@ -499,14 +522,14 @@ switch (pair->key) { case 104: - room = pair->value; + room = yahoo_string_decode(gc, pair->value, FALSE); break; case 129: /* room id? */ break; case 126: /* ??? */ break; case 117: - msg = pair->value; + msg = yahoo_string_decode(gc, pair->value, FALSE); break; case 119: who = pair->value; @@ -523,6 +546,10 @@ g_hash_table_replace(components, g_strdup("room"), g_strdup(room)); serv_got_chat_invite(gc, room, who, msg, components); } + if (room) + g_free(room); + if (msg) + g_free(msg); } void yahoo_process_chat_goto(GaimConnection *gc, struct yahoo_packet *pkt) @@ -535,6 +562,7 @@ /* * Functions dealing with conferences + * I think conference names are always ascii. */ static void yahoo_conf_leave(struct yahoo_data *yd, const char *room, const char *dn, GList *who) @@ -557,14 +585,18 @@ yahoo_packet_free(pkt); } -static int yahoo_conf_send(struct yahoo_data *yd, const char *dn, const char *room, +static int yahoo_conf_send(GaimConnection *gc, const char *dn, const char *room, GList *members, const char *what) { + struct yahoo_data *yd = gc->proto_data; struct yahoo_packet *pkt; GList *who; - char *msg; + char *msg, *msg2; + int utf8 = 1; msg = yahoo_html_to_codes(what); + msg2 = yahoo_string_encode(gc, msg, &utf8); + pkt = yahoo_packet_new(YAHOO_SERVICE_CONFMSG, YAHOO_STATUS_AVAILABLE, 0); @@ -572,13 +604,15 @@ for (who = members; who; who = who->next) yahoo_packet_hash(pkt, 53, (char *)who->data); yahoo_packet_hash(pkt, 57, room); - yahoo_packet_hash(pkt, 14, msg); - yahoo_packet_hash(pkt, 97, "1"); /* utf-8 */ + yahoo_packet_hash(pkt, 14, msg2); + if (utf8) + yahoo_packet_hash(pkt, 97, "1"); /* utf-8 */ yahoo_send_packet(yd, pkt); yahoo_packet_free(pkt); g_free(msg); + g_free(msg2); return 0; } @@ -615,11 +649,16 @@ g_strfreev(memarr); } -static void yahoo_conf_invite(struct yahoo_data *yd, GaimConversation *c, +static void yahoo_conf_invite(GaimConnection *gc, GaimConversation *c, const char *dn, const char *buddy, const char *room, const char *msg) { + struct yahoo_data *yd = gc->proto_data; struct yahoo_packet *pkt; GList *members; + char *msg2 = NULL; + + if (msg) + msg2 = yahoo_string_encode(gc, msg, NULL); members = gaim_conv_chat_get_users(GAIM_CONV_CHAT(c)); @@ -628,7 +667,7 @@ yahoo_packet_hash(pkt, 1, dn); yahoo_packet_hash(pkt, 51, buddy); yahoo_packet_hash(pkt, 57, room); - yahoo_packet_hash(pkt, 58, msg?msg:""); + yahoo_packet_hash(pkt, 58, msg?msg2:""); yahoo_packet_hash(pkt, 13, "0"); for(; members; members = members->next) { if (!strcmp(members->data, dn)) @@ -639,6 +678,8 @@ yahoo_send_packet(yd, pkt); yahoo_packet_free(pkt); + if (msg) + g_free(msg2); } /* @@ -650,10 +691,13 @@ struct yahoo_data *yd = gc->proto_data; struct yahoo_packet *pkt; GaimConversation *c; + char *eroom; + + eroom = yahoo_string_encode(gc, room, NULL); pkt = yahoo_packet_new(YAHOO_SERVICE_CHATEXIT, YAHOO_STATUS_AVAILABLE, 0); - yahoo_packet_hash(pkt, 104, room); + yahoo_packet_hash(pkt, 104, eroom); yahoo_packet_hash(pkt, 109, dn); yahoo_packet_hash(pkt, 108, "1"); yahoo_packet_hash(pkt, 112, "0"); /* what does this one mean? */ @@ -681,6 +725,7 @@ yahoo_packet_free(pkt); yd->chat_online = 0; + g_free(eroom); } /* borrowed from gtkconv.c */ @@ -722,11 +767,13 @@ return FALSE; } -static int yahoo_chat_send(struct yahoo_data *yd, const char *dn, const char *room, const char *what) +static int yahoo_chat_send(GaimConnection *gc, const char *dn, const char *room, const char *what) { + struct yahoo_data *yd = gc->proto_data; struct yahoo_packet *pkt; int me = 0; - char *msg1, *msg2; + char *msg1, *msg2, *room2; + gboolean utf8 = TRUE; msg1 = g_strdup(what); @@ -735,55 +782,75 @@ msg2 = yahoo_html_to_codes(msg1); g_free(msg1); + msg1 = yahoo_string_encode(gc, msg2, &utf8); + g_free(msg2); + room2 = yahoo_string_encode(gc, room, NULL); pkt = yahoo_packet_new(YAHOO_SERVICE_COMMENT, YAHOO_STATUS_AVAILABLE, 0); yahoo_packet_hash(pkt, 1, dn); - yahoo_packet_hash(pkt, 104, room); - yahoo_packet_hash(pkt, 117, msg2); + yahoo_packet_hash(pkt, 104, room2); + yahoo_packet_hash(pkt, 117, msg1); if (me) yahoo_packet_hash(pkt, 124, "2"); else yahoo_packet_hash(pkt, 124, "1"); /* fixme: what about /think? (124=3) */ + if (utf8) + yahoo_packet_hash(pkt, 97, "1"); yahoo_send_packet(yd, pkt); yahoo_packet_free(pkt); - g_free(msg2); + g_free(msg1); + g_free(room2); return 0; } -static void yahoo_chat_join(struct yahoo_data *yd, const char *dn, const char *room, const char *topic) +static void yahoo_chat_join(GaimConnection *gc, const char *dn, const char *room, const char *topic) { + struct yahoo_data *yd = gc->proto_data; struct yahoo_packet *pkt; + char *room2; + + room2 = yahoo_string_encode(gc, room, NULL); pkt = yahoo_packet_new(YAHOO_SERVICE_CHATJOIN, YAHOO_STATUS_AVAILABLE, 0); yahoo_packet_hash(pkt, 62, "2"); - yahoo_packet_hash(pkt, 104, room); + yahoo_packet_hash(pkt, 104, room2); yahoo_packet_hash(pkt, 129, "0"); yahoo_send_packet(yd, pkt); yahoo_packet_free(pkt); + g_free(room2); } -static void yahoo_chat_invite(struct yahoo_data *yd, const char *dn, const char *buddy, +static void yahoo_chat_invite(GaimConnection *gc, const char *dn, const char *buddy, const char *room, const char *msg) { + struct yahoo_data *yd = gc->proto_data; struct yahoo_packet *pkt; + char *room2, *msg2 = NULL; + room2 = yahoo_string_encode(gc, room, NULL); + if (msg) + msg2 = yahoo_string_encode(gc, msg, NULL); pkt = yahoo_packet_new(YAHOO_SERVICE_CHATADDINVITE, YAHOO_STATUS_AVAILABLE, 0); yahoo_packet_hash(pkt, 1, dn); yahoo_packet_hash(pkt, 118, buddy); - yahoo_packet_hash(pkt, 104, room); - yahoo_packet_hash(pkt, 117, (msg?msg:"")); + yahoo_packet_hash(pkt, 104, room2); + yahoo_packet_hash(pkt, 117, (msg2?msg2:"")); yahoo_packet_hash(pkt, 129, "0"); yahoo_send_packet(yd, pkt); yahoo_packet_free(pkt); + + g_free(room2); + if (msg2) + g_free(msg2); } void yahoo_chat_goto(GaimConnection *gc, const char *name) @@ -849,10 +916,10 @@ return -1; if (id != YAHOO_CHAT_ID) { - ret = yahoo_conf_send(yd, gaim_connection_get_display_name(gc), + ret = yahoo_conf_send(gc, gaim_connection_get_display_name(gc), gaim_conversation_get_name(c), gaim_conv_chat_get_users(GAIM_CONV_CHAT(c)), what); } else { - ret = yahoo_chat_send(yd, gaim_connection_get_display_name(gc), + ret = yahoo_chat_send(gc, gaim_connection_get_display_name(gc), gaim_conversation_get_name(c), what); if (!ret) serv_got_chat_in(gc, gaim_conv_chat_get_id(GAIM_CONV_CHAT(c)), @@ -910,14 +977,13 @@ FALSE); if (!yd->chat_online) yahoo_chat_online(gc); - yahoo_chat_join(yd, gaim_connection_get_display_name(gc), room, topic); + yahoo_chat_join(gc, gaim_connection_get_display_name(gc), room, topic); return; } } void yahoo_c_invite(GaimConnection *gc, int id, const char *msg, const char *name) { - struct yahoo_data *yd = (struct yahoo_data *) gc->proto_data; GaimConversation *c; c = gaim_find_chat(gc, id); @@ -925,10 +991,10 @@ return; if (id != YAHOO_CHAT_ID) { - yahoo_conf_invite(yd, c, gaim_connection_get_display_name(gc), name, + yahoo_conf_invite(gc, c, gaim_connection_get_display_name(gc), name, gaim_conversation_get_name(c), msg); } else { - yahoo_chat_invite(yd, gaim_connection_get_display_name(gc), name, + yahoo_chat_invite(gc, gaim_connection_get_display_name(gc), name, gaim_conversation_get_name(c), msg); } }