# HG changeset patch # User Mark Doliner # Date 1050295962 0 # Node ID c19cc54f4df69d4b9348817bded0ae26c29ec368 # Parent 29a834316b343509bc4099999ab93848e814fb45 [gaim-migrate @ 5492] Stuff I did (in order from most important to least): -Made set away message and set profile count the number of bytes rather than the number of characters. This fixes the lack of a warning dialog when setting info that needs an encoding other than ascii or iso8859-1. (Because "hi" in UCS-2BE is 4 bytes but "hi" in utf8 is only 2.) -Created an oscar_encoding_to_utf8 function to convert from a given encoding to utf8. This is AIM/ICQ specific. -Added a "Profile:" and "Away Message:" line to the get info response window. Is it better this way or without it? I thought it would be good if there was a way for users to tell which text was the away message and which was the info, but I also think this solution could be nicer looking. -Added a little check for some server icon stuff because someone reported an obscure crash. -Shuffled some stuff around in oscar.c -Bouldered on the little wall outside of the gym today. It's much more difficult than climbing inside. I think my forearms are just a bit too weak. The holds are tiny, though. committer: Tailor Script diff -r 29a834316b34 -r c19cc54f4df6 src/protocols/oscar/oscar.c --- a/src/protocols/oscar/oscar.c Mon Apr 14 01:53:12 2003 +0000 +++ b/src/protocols/oscar/oscar.c Mon Apr 14 04:52:42 2003 +0000 @@ -199,12 +199,197 @@ gchar *nick; }; +static char *msgerrreason[] = { + N_("Invalid error"), + N_("Invalid SNAC"), + N_("Rate to host"), + N_("Rate to client"), + N_("Not logged in"), + N_("Service unavailable"), + N_("Service not defined"), + N_("Obsolete SNAC"), + N_("Not supported by host"), + N_("Not supported by client"), + N_("Refused by client"), + N_("Reply too big"), + N_("Responses lost"), + N_("Request denied"), + N_("Busted SNAC payload"), + N_("Insufficient rights"), + N_("In local permit/deny"), + N_("Too evil (sender)"), + N_("Too evil (receiver)"), + N_("User temporarily unavailable"), + N_("No match"), + N_("List overflow"), + N_("Request ambiguous"), + N_("Queue full"), + N_("Not while on AOL") +}; +static int msgerrreasonlen = 25; + +/* All the libfaim->gaim callback functions */ +static int gaim_parse_auth_resp (aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_login (aim_session_t *, aim_frame_t *, ...); +static int gaim_handle_redirect (aim_session_t *, aim_frame_t *, ...); +static int gaim_info_change (aim_session_t *, aim_frame_t *, ...); +static int gaim_account_confirm (aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_oncoming (aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_offgoing (aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_incoming_im(aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_misses (aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_clientauto (aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_user_info (aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_motd (aim_session_t *, aim_frame_t *, ...); +static int gaim_chatnav_info (aim_session_t *, aim_frame_t *, ...); +static int gaim_chat_join (aim_session_t *, aim_frame_t *, ...); +static int gaim_chat_leave (aim_session_t *, aim_frame_t *, ...); +static int gaim_chat_info_update (aim_session_t *, aim_frame_t *, ...); +static int gaim_chat_incoming_msg(aim_session_t *, aim_frame_t *, ...); +static int gaim_email_parseupdate(aim_session_t *, aim_frame_t *, ...); +static int gaim_icon_error (aim_session_t *, aim_frame_t *, ...); +static int gaim_icon_parseicon (aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_msgack (aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_ratechange (aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_evilnotify (aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_searcherror(aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_searchreply(aim_session_t *, aim_frame_t *, ...); +static int gaim_bosrights (aim_session_t *, aim_frame_t *, ...); +static int gaim_connerr (aim_session_t *, aim_frame_t *, ...); +static int conninitdone_admin (aim_session_t *, aim_frame_t *, ...); +static int conninitdone_bos (aim_session_t *, aim_frame_t *, ...); +static int conninitdone_chatnav (aim_session_t *, aim_frame_t *, ...); +static int conninitdone_chat (aim_session_t *, aim_frame_t *, ...); +static int conninitdone_email (aim_session_t *, aim_frame_t *, ...); +static int conninitdone_icon (aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_msgerr (aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_mtn (aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_locaterights(aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_buddyrights(aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_locerr (aim_session_t *, aim_frame_t *, ...); +static int gaim_icbm_param_info (aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_genericerr (aim_session_t *, aim_frame_t *, ...); +static int gaim_memrequest (aim_session_t *, aim_frame_t *, ...); +static int gaim_selfinfo (aim_session_t *, aim_frame_t *, ...); +static int gaim_offlinemsg (aim_session_t *, aim_frame_t *, ...); +static int gaim_offlinemsgdone (aim_session_t *, aim_frame_t *, ...); +static int gaim_icqalias (aim_session_t *, aim_frame_t *, ...); +static int gaim_icqinfo (aim_session_t *, aim_frame_t *, ...); +static int gaim_popup (aim_session_t *, aim_frame_t *, ...); +#ifndef NOSSI +static int gaim_ssi_parseerr (aim_session_t *, aim_frame_t *, ...); +static int gaim_ssi_parserights (aim_session_t *, aim_frame_t *, ...); +static int gaim_ssi_parselist (aim_session_t *, aim_frame_t *, ...); +static int gaim_ssi_parseack (aim_session_t *, aim_frame_t *, ...); +static int gaim_ssi_authgiven (aim_session_t *, aim_frame_t *, ...); +static int gaim_ssi_authrequest (aim_session_t *, aim_frame_t *, ...); +static int gaim_ssi_authreply (aim_session_t *, aim_frame_t *, ...); +static int gaim_ssi_gotadded (aim_session_t *, aim_frame_t *, ...); +#endif + +/* for DirectIM/image transfer */ +static int gaim_odc_initiate (aim_session_t *, aim_frame_t *, ...); +static int gaim_odc_incoming (aim_session_t *, aim_frame_t *, ...); +static int gaim_odc_typing (aim_session_t *, aim_frame_t *, ...); +static int gaim_update_ui (aim_session_t *, aim_frame_t *, ...); + +/* for file transfer */ +static int oscar_sendfile_estblsh(aim_session_t *, aim_frame_t *, ...); +static int oscar_sendfile_prompt (aim_session_t *, aim_frame_t *, ...); +static int oscar_sendfile_ack (aim_session_t *, aim_frame_t *, ...); +static int oscar_sendfile_done (aim_session_t *, aim_frame_t *, ...); + +/* for icons */ +static gboolean gaim_icon_timerfunc(gpointer data); + static void gaim_free_name_data(struct name_data *data) { g_free(data->name); g_free(data->nick); g_free(data); } +static fu32_t oscar_encoding_check(const char *utf8) +{ + int i = 0; + fu32_t encodingflag = 0; + + /* Determine how we can send this message. Per the warnings elsewhere + * in this file, these little checks determine the simplest encoding + * we can use for a given message send using it. */ + while (utf8[i]) { + if ((unsigned char)utf8[i] > 0x7f) { + /* not ASCII! */ + encodingflag = AIM_IMFLAGS_ISO_8859_1; + break; + } + i++; + } + while (utf8[i]) { + /* ISO-8859-1 is 0x00-0xbf in the first byte + * followed by 0xc0-0xc3 in the second */ + if ((unsigned char)utf8[i] < 0x80) { + i++; + continue; + } else if (((unsigned char)utf8[i] & 0xfc) == 0xc0 && + ((unsigned char)utf8[i + 1] & 0xc0) == 0x80) { + i += 2; + continue; + } + encodingflag = AIM_IMFLAGS_UNICODE; + break; + } + + return encodingflag; +} + +static fu32_t oscar_encoding_parse(const char *enc) +{ + char *charset; + + /* If anything goes wrong, fall back on ASCII and print a message */ + if (enc == NULL) { + debug_printf("Encoding was null, that's odd\n"); + return 0; + } + charset = strstr(enc, "charset="); + if (charset == NULL) { + debug_printf("No charset specified for info, assuming ASCII\n"); + return 0; + } + charset += 8; + if (!strcmp(charset, "\"us-ascii\"") || !strcmp(charset, "\"utf-8\"")) { + /* UTF-8 is our native charset, ASCII is a proper subset */ + return 0; + } else if (!strcmp(charset, "\"iso-8859-1\"")) { + return AIM_IMFLAGS_ISO_8859_1; + } else if (!strcmp(charset, "\"unicode-2-0\"")) { + return AIM_IMFLAGS_UNICODE; + } else { + debug_printf("Unrecognized character set '%s', using ASCII\n", charset); + return 0; + } +} + +gchar *oscar_encoding_to_utf8(const char *encoding, char *text, int textlen) +{ + gchar *utf8 = NULL; + int flags = oscar_encoding_parse(encoding); + + switch (flags) { + case 0: + utf8 = g_strndup(text, textlen); + break; + case AIM_IMFLAGS_ISO_8859_1: + utf8 = g_convert(text, textlen, "UTF-8", "ISO-8859-1", NULL, NULL, NULL); + break; + case AIM_IMFLAGS_UNICODE: + utf8 = g_convert(text, textlen, "UTF-8", "UCS-2BE", NULL, NULL, NULL); + break; + } + + return utf8; +} + static struct direct_im *find_direct_im(struct oscar_data *od, const char *who) { GSList *d = od->direct_ims; struct direct_im *m = NULL; @@ -279,112 +464,6 @@ return c; } -/* All the libfaim->gaim callback functions */ -static int gaim_parse_auth_resp (aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_login (aim_session_t *, aim_frame_t *, ...); -static int gaim_handle_redirect (aim_session_t *, aim_frame_t *, ...); -static int gaim_info_change (aim_session_t *, aim_frame_t *, ...); -static int gaim_account_confirm (aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_oncoming (aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_offgoing (aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_incoming_im(aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_misses (aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_clientauto (aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_user_info (aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_motd (aim_session_t *, aim_frame_t *, ...); -static int gaim_chatnav_info (aim_session_t *, aim_frame_t *, ...); -static int gaim_chat_join (aim_session_t *, aim_frame_t *, ...); -static int gaim_chat_leave (aim_session_t *, aim_frame_t *, ...); -static int gaim_chat_info_update (aim_session_t *, aim_frame_t *, ...); -static int gaim_chat_incoming_msg(aim_session_t *, aim_frame_t *, ...); -static int gaim_email_parseupdate(aim_session_t *, aim_frame_t *, ...); -static int gaim_icon_error (aim_session_t *, aim_frame_t *, ...); -static int gaim_icon_parseicon (aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_msgack (aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_ratechange (aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_evilnotify (aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_searcherror(aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_searchreply(aim_session_t *, aim_frame_t *, ...); -static int gaim_bosrights (aim_session_t *, aim_frame_t *, ...); -static int gaim_connerr (aim_session_t *, aim_frame_t *, ...); -static int conninitdone_admin (aim_session_t *, aim_frame_t *, ...); -static int conninitdone_bos (aim_session_t *, aim_frame_t *, ...); -static int conninitdone_chatnav (aim_session_t *, aim_frame_t *, ...); -static int conninitdone_chat (aim_session_t *, aim_frame_t *, ...); -static int conninitdone_email (aim_session_t *, aim_frame_t *, ...); -static int conninitdone_icon (aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_msgerr (aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_mtn (aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_locaterights(aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_buddyrights(aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_locerr (aim_session_t *, aim_frame_t *, ...); -static int gaim_icbm_param_info (aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_genericerr (aim_session_t *, aim_frame_t *, ...); -static int gaim_memrequest (aim_session_t *, aim_frame_t *, ...); -static int gaim_selfinfo (aim_session_t *, aim_frame_t *, ...); -static int gaim_offlinemsg (aim_session_t *, aim_frame_t *, ...); -static int gaim_offlinemsgdone (aim_session_t *, aim_frame_t *, ...); -static int gaim_icqalias (aim_session_t *, aim_frame_t *, ...); -static int gaim_icqinfo (aim_session_t *, aim_frame_t *, ...); -static int gaim_popup (aim_session_t *, aim_frame_t *, ...); -#ifndef NOSSI -static int gaim_ssi_parseerr (aim_session_t *, aim_frame_t *, ...); -static int gaim_ssi_parserights (aim_session_t *, aim_frame_t *, ...); -static int gaim_ssi_parselist (aim_session_t *, aim_frame_t *, ...); -static int gaim_ssi_parseack (aim_session_t *, aim_frame_t *, ...); -static int gaim_ssi_authgiven (aim_session_t *, aim_frame_t *, ...); -static int gaim_ssi_authrequest (aim_session_t *, aim_frame_t *, ...); -static int gaim_ssi_authreply (aim_session_t *, aim_frame_t *, ...); -static int gaim_ssi_gotadded (aim_session_t *, aim_frame_t *, ...); -#endif - -/* for DirectIM/image transfer */ -static int gaim_odc_initiate (aim_session_t *, aim_frame_t *, ...); -static int gaim_odc_incoming (aim_session_t *, aim_frame_t *, ...); -static int gaim_odc_typing (aim_session_t *, aim_frame_t *, ...); -static int gaim_update_ui (aim_session_t *, aim_frame_t *, ...); - -/* for file transfer */ -static int oscar_sendfile_estblsh(aim_session_t *, aim_frame_t *, ...); -static int oscar_sendfile_prompt (aim_session_t *, aim_frame_t *, ...); -static int oscar_sendfile_ack (aim_session_t *, aim_frame_t *, ...); -static int oscar_sendfile_done (aim_session_t *, aim_frame_t *, ...); - -/* for icons */ -static gboolean gaim_icon_timerfunc(gpointer data); - -static fu32_t check_encoding(const char *utf8); -static fu32_t parse_encoding(const char *enc); - -static char *msgerrreason[] = { - N_("Invalid error"), - N_("Invalid SNAC"), - N_("Rate to host"), - N_("Rate to client"), - N_("Not logged in"), - N_("Service unavailable"), - N_("Service not defined"), - N_("Obsolete SNAC"), - N_("Not supported by host"), - N_("Not supported by client"), - N_("Refused by client"), - N_("Reply too big"), - N_("Responses lost"), - N_("Request denied"), - N_("Busted SNAC payload"), - N_("Insufficient rights"), - N_("In local permit/deny"), - N_("Too evil (sender)"), - N_("Too evil (receiver)"), - N_("User temporarily unavailable"), - N_("No match"), - N_("List overflow"), - N_("Request ambiguous"), - N_("Queue full"), - N_("Not while on AOL") -}; -static int msgerrreasonlen = 25; - static void gaim_odc_disconnect(aim_session_t *sess, aim_conn_t *conn) { struct gaim_connection *gc = sess->aux_data; struct oscar_data *od = (struct oscar_data *)gc->proto_data; @@ -3046,7 +3125,6 @@ GSList *l = od->evilhack; gboolean evilhack = FALSE; gchar *membersince = NULL, *onlinesince = NULL, *idle = NULL; - fu32_t flags; va_list ap; aim_userinfo_t *info; fu16_t infotype; @@ -3062,18 +3140,7 @@ va_end(ap); if (text_len > 0) { - flags = parse_encoding (text_enc); - switch (flags) { - case 0: - utf8 = g_strndup(text, text_len); - break; - case AIM_IMFLAGS_ISO_8859_1: - utf8 = g_convert(text, text_len, "UTF-8", "ISO-8859-1", NULL, NULL, NULL); - break; - case AIM_IMFLAGS_UNICODE: - utf8 = g_convert(text, text_len, "UTF-8", "UCS-2BE", NULL, NULL, NULL); - break; - default: + if (!(utf8 = oscar_encoding_to_utf8(text_enc, text, text_len))) { utf8 = g_strdup(_("Unable to display information because it was sent in an unknown encoding.")); debug_printf("Encountered an unknown encoding while parsing userinfo\n"); } @@ -3133,6 +3200,7 @@ } else { g_show_info_text(gc, info->sn, 0, header, + (utf8 && *utf8) ? _("Away Message:
") : NULL, (utf8 && *utf8) ? away_subs(utf8, gc->username) : NULL, (utf8 && *utf8) ? "
" : NULL, NULL); @@ -3146,8 +3214,8 @@ NULL); } else { g_show_info_text(gc, info->sn, 1, - (utf8 && *utf8) ? away_subs(utf8, gc->username) : - _("No Information Provided"), + (utf8 && *utf8) ? _("Profile:
") : _("No Information Provided"), + (utf8 && *utf8) ? away_subs(utf8, gc->username) : NULL, NULL); } @@ -3400,14 +3468,14 @@ if (iconlen > 0) { char *b16; - struct buddy *b; + struct buddy *b = gaim_find_buddy(gc->account, sn); set_icon_data(gc, sn, icon, iconlen); b16 = tobase16(iconcsum, iconcsumlen); - b = gaim_find_buddy(gc->account, sn); - gaim_buddy_set_setting(b, "icon_checksum", b16); - gaim_blist_save(); - if(b16) + if (b16) { + gaim_buddy_set_setting(b, "icon_checksum", b16); + gaim_blist_save(); free(b16); + } } cur = od->requesticon; @@ -3699,7 +3767,7 @@ if (od->icq) aim_bos_setprofile(sess, fr->conn, NULL, NULL, 0, NULL, NULL, 0, caps_icq); else { - flags = check_encoding (gc->account->user_info); + flags = oscar_encoding_check (gc->account->user_info); if (flags == 0) { aim_bos_setprofile(sess, fr->conn, "us-ascii", gc->account->user_info, @@ -4197,7 +4265,7 @@ args.destsn = name; len = strlen(message); - args.flags |= check_encoding(message); + args.flags |= oscar_encoding_check(message); if (args.flags & AIM_IMFLAGS_UNICODE) { debug_printf("Sending Unicode IM\n"); args.charset = 0x0002; @@ -4277,98 +4345,110 @@ } -static void oscar_set_idle(struct gaim_connection *g, int time) { - struct oscar_data *od = (struct oscar_data *)g->proto_data; +static void oscar_set_idle(struct gaim_connection *gc, int time) { + struct oscar_data *od = (struct oscar_data *)gc->proto_data; aim_bos_setidle(od->sess, od->conn, time); } -static void oscar_set_info(struct gaim_connection *g, char *info) { - struct oscar_data *od = (struct oscar_data *)g->proto_data; - gchar *inforeal, *unicode; - fu32_t flags; - int unicode_len; +static void oscar_set_info(struct gaim_connection *gc, char *text) { + struct oscar_data *od = (struct oscar_data *)gc->proto_data; + fu32_t flags = 0; + char *msg = NULL; + int msglen = 0; if (od->rights.maxsiglen == 0) do_error_dialog(_("Unable to set AIM profile."), _("You have probably requested to set your profile before the login procedure completed. " - "Your profile remains unset; try setting it again when you are fully connected."), GAIM_ERROR); - - if (strlen(info) > od->rights.maxsiglen) { - gchar *errstr; - - errstr = g_strdup_printf(_("The maximum profile length of %d bytes has been exceeded. " - "Gaim has truncated and set it."), od->rights.maxsiglen); - do_error_dialog("Profile too long.", errstr, GAIM_WARNING); - - g_free(errstr); - } - - inforeal = g_strndup(info, od->rights.maxsiglen); + "Your profile remains unset; try setting it again when you are fully connected."), GAIM_WARNING); if (od->icq) aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, NULL, NULL, 0, caps_icq); else { - flags = check_encoding(inforeal); - - if (flags == 0) { - aim_bos_setprofile(od->sess, od->conn, "us-ascii", inforeal, strlen (inforeal), - NULL, NULL, 0, caps_aim); + if (!text) { + aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, NULL, NULL, 0, caps_aim); + return; + } + + flags = oscar_encoding_check(text); + if (flags & AIM_IMFLAGS_UNICODE) { + msg = g_convert(text, strlen(text), "UCS-2BE", "UTF-8", NULL, &msglen, NULL); + aim_bos_setprofile(od->sess, od->conn, "unicode-2-0", msg, (msglen > od->rights.maxsiglen ? od->rights.maxsiglen : msglen), NULL, NULL, 0, caps_aim); + g_free(msg); + gc->away = g_strndup(text, od->rights.maxsiglen/2); + } else if (flags & AIM_IMFLAGS_ISO_8859_1) { + msg = g_convert(text, strlen(text), "ISO-8859-1", "UTF-8", NULL, &msglen, NULL); + aim_bos_setprofile(od->sess, od->conn, "iso-8859-1", msg, (msglen > od->rights.maxsiglen ? od->rights.maxsiglen : msglen), NULL, NULL, 0, caps_aim); + g_free(msg); + gc->away = g_strndup(text, od->rights.maxsiglen); } else { - unicode = g_convert (inforeal, strlen(inforeal), "UCS-2BE", "UTF-8", NULL, - &unicode_len, NULL); - aim_bos_setprofile(od->sess, od->conn, "unicode-2-0", unicode, unicode_len, - NULL, NULL, 0, caps_aim); - g_free(unicode); + msglen = strlen(text); + aim_bos_setprofile(od->sess, od->conn, "us-ascii", text, (msglen > od->rights.maxsiglen ? od->rights.maxsiglen : msglen), NULL, NULL, 0, caps_aim); + gc->away = g_strndup(text, od->rights.maxsiglen); } - } - g_free(inforeal); + + if (msglen > od->rights.maxsiglen) { + gchar *errstr; + errstr = g_strdup_printf(_("The maximum profile length of %d bytes has been exceeded. " + "Gaim has truncated it for you."), od->rights.maxsiglen); + do_error_dialog(_("Profile too long."), errstr, GAIM_WARNING); + g_free(errstr); + } + + } return; } -static void oscar_set_away_aim(struct gaim_connection *gc, struct oscar_data *od, const char *message) +static void oscar_set_away_aim(struct gaim_connection *gc, struct oscar_data *od, const char *text) { - fu32_t flags; - char *unicode; - int unicode_len; + fu32_t flags = 0; + char *msg = NULL; + int msglen = 0; if (od->rights.maxawaymsglen == 0) do_error_dialog(_("Unable to set AIM away message."), _("You have probably requested to set your away message before the login procedure completed. " - "You remain in a \"present\" state; try setting it again when you are fully connected."), GAIM_ERROR); - + "You remain in a \"present\" state; try setting it again when you are fully connected."), GAIM_WARNING); + if (gc->away) { g_free(gc->away); gc->away = NULL; } - if (!message) { + if (!text) { aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, NULL, "", 0, caps_aim); return; } - if (strlen(message) > od->rights.maxawaymsglen) { + flags = oscar_encoding_check(text); + if (flags & AIM_IMFLAGS_UNICODE) { + msg = g_convert(text, strlen(text), "UCS-2BE", "UTF-8", NULL, &msglen, NULL); + aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, "unicode-2-0", msg, + (msglen > od->rights.maxawaymsglen ? od->rights.maxawaymsglen : msglen), caps_aim); + g_free(msg); + gc->away = g_strndup(text, od->rights.maxawaymsglen/2); + } else if (flags & AIM_IMFLAGS_ISO_8859_1) { + msg = g_convert(text, strlen(text), "ISO-8859-1", "UTF-8", NULL, &msglen, NULL); + aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, "iso-8859-1", msg, + (msglen > od->rights.maxawaymsglen ? od->rights.maxawaymsglen : msglen), caps_aim); + g_free(msg); + gc->away = g_strndup(text, od->rights.maxawaymsglen); + } else { + msglen = strlen(text); + aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, "us-ascii", text, + (msglen > od->rights.maxawaymsglen ? od->rights.maxawaymsglen : msglen), caps_aim); + gc->away = g_strndup(text, od->rights.maxawaymsglen); + } + + if (msglen > od->rights.maxawaymsglen) { gchar *errstr; - errstr = g_strdup_printf(_("The away message length of %d bytes has been exceeded. " + errstr = g_strdup_printf(_("The maximum away message length of %d bytes has been exceeded. " "Gaim has truncated it and set you away."), od->rights.maxawaymsglen); - do_error_dialog("Away message too long.", errstr, GAIM_WARNING); + do_error_dialog(_("Away message too long."), errstr, GAIM_WARNING); g_free(errstr); } - gc->away = g_strndup(message, od->rights.maxawaymsglen); - flags = check_encoding(message); - - if (flags == 0) { - aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, "us-ascii", gc->away, strlen(gc->away), - caps_aim); - } else { - unicode = g_convert(message, strlen(message), "UCS-2BE", "UTF-8", NULL, &unicode_len, NULL); - aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, "unicode-2-0", unicode, unicode_len, - caps_aim); - g_free(unicode); - } - return; } @@ -5781,69 +5861,6 @@ g_free(dim); } -static fu32_t check_encoding(const char *utf8) -{ - int i = 0; - fu32_t encodingflag = 0; - - /* Determine how we can send this message. Per the - * warnings elsewhere in this file, these little - * checks determine the simplest encoding we can use - * for a given message send using it. */ - while (utf8[i]) { - if ((unsigned char)utf8[i] > 0x7f) { - /* not ASCII! */ - encodingflag = AIM_IMFLAGS_ISO_8859_1; - break; - } - i++; - } - while (utf8[i]) { - /* ISO-8859-1 is 0x00-0xbf in the first byte - * followed by 0xc0-0xc3 in the second */ - if ((unsigned char)utf8[i] < 0x80) { - i++; - continue; - } else if (((unsigned char)utf8[i] & 0xfc) == 0xc0 && - ((unsigned char)utf8[i + 1] & 0xc0) == 0x80) { - i += 2; - continue; - } - encodingflag = AIM_IMFLAGS_UNICODE; - break; - } - - return encodingflag; -} - -static fu32_t parse_encoding(const char *enc) -{ - char *charset; - - /* If anything goes wrong, fall back on ASCII and print a message */ - if (enc == NULL) { - debug_printf("Encoding was null, that's odd\n"); - return 0; - } - charset = strstr(enc, "charset="); - if (charset == NULL) { - debug_printf("No charset specified for info, assuming ASCII\n"); - return 0; - } - charset += 8; - if (!strcmp(charset, "\"us-ascii\"") || !strcmp(charset, "\"utf-8\"")) { - /* UTF-8 is our native charset, ASCII is a proper subset */ - return 0; - } else if (!strcmp(charset, "\"iso-8859-1\"")) { - return AIM_IMFLAGS_ISO_8859_1; - } else if (!strcmp(charset, "\"unicode-2-0\"")) { - return AIM_IMFLAGS_UNICODE; - } else { - debug_printf("Unrecognized character set '%s', using ASCII\n", charset); - return 0; - } -} - G_MODULE_EXPORT void oscar_init(struct prpl *ret) { struct proto_user_opt *puo; ret->protocol = PROTO_OSCAR;