Mercurial > pidgin.yaz
changeset 30828:1dd3ed053628
explicit merge of '92760ff5074d9bcc75f59473f013ca8a959a85b8'
and 'eadc83c534fbbc673a6876ddb1e0bdac8428c07b'
author | ivan.komarov@soc.pidgin.im |
---|---|
date | Thu, 29 Jul 2010 00:06:56 +0000 |
parents | bbb27d65681f (diff) b8f47c07ca42 (current diff) |
children | 1b7152eeea31 |
files | libpurple/protocols/oscar/family_advert.c libpurple/protocols/oscar/family_invite.c libpurple/protocols/oscar/family_odir.c libpurple/protocols/oscar/family_translate.c libpurple/protocols/oscar/oscar.c |
diffstat | 32 files changed, 486 insertions(+), 3849 deletions(-) [+] |
line wrap: on
line diff
--- a/libpurple/protocols/oscar/Makefile.am Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/Makefile.am Thu Jul 29 00:06:56 2010 +0000 @@ -9,8 +9,8 @@ authorization.c \ bstream.c \ clientlogin.c \ + encoding.c \ family_admin.c \ - family_advert.c \ family_alert.c \ family_auth.c \ family_bart.c \ @@ -20,14 +20,11 @@ family_chatnav.c \ family_icq.c \ family_icbm.c \ - family_invite.c \ family_locate.c \ - family_odir.c \ family_oservice.c \ family_popup.c \ family_feedbag.c \ family_stats.c \ - family_translate.c \ family_userlookup.c \ flap_connection.c \ misc.c \
--- a/libpurple/protocols/oscar/bstream.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/bstream.c Thu Jul 29 00:06:56 2010 +0000 @@ -34,7 +34,6 @@ int byte_stream_init(ByteStream *bs, guint8 *data, int len) { - if (bs == NULL) return -1; @@ -50,7 +49,7 @@ g_free(bs->data); } -int byte_stream_empty(ByteStream *bs) +int byte_stream_bytes_left(ByteStream *bs) { return bs->len - bs->offset; } @@ -62,102 +61,74 @@ int byte_stream_setpos(ByteStream *bs, unsigned int off) { - - if (off > bs->len) - return -1; + g_return_val_if_fail(off <= bs->len, -1); bs->offset = off; - return off; } void byte_stream_rewind(ByteStream *bs) { - byte_stream_setpos(bs, 0); - - return; } /* * N can be negative, which can be used for going backwards - * in a bstream. I'm not sure if libfaim actually does - * this anywhere... + * in a bstream. */ int byte_stream_advance(ByteStream *bs, int n) { - - if ((byte_stream_curpos(bs) + n < 0) || (byte_stream_empty(bs) < n)) - return 0; /* XXX throw an exception */ + g_return_val_if_fail((byte_stream_curpos(bs) + n >= 0) && (n <= byte_stream_bytes_left(bs)), 0); bs->offset += n; - return n; } guint8 byte_stream_get8(ByteStream *bs) { - - if (byte_stream_empty(bs) < 1) - return 0; /* XXX throw an exception */ + g_return_val_if_fail(byte_stream_bytes_left(bs) >= 1, 0); bs->offset++; - return aimutil_get8(bs->data + bs->offset - 1); } guint16 byte_stream_get16(ByteStream *bs) { - - if (byte_stream_empty(bs) < 2) - return 0; /* XXX throw an exception */ + g_return_val_if_fail(byte_stream_bytes_left(bs) >= 2, 0); bs->offset += 2; - return aimutil_get16(bs->data + bs->offset - 2); } guint32 byte_stream_get32(ByteStream *bs) { - - if (byte_stream_empty(bs) < 4) - return 0; /* XXX throw an exception */ + g_return_val_if_fail(byte_stream_bytes_left(bs) >= 4, 0); bs->offset += 4; - return aimutil_get32(bs->data + bs->offset - 4); } guint8 byte_stream_getle8(ByteStream *bs) { - - if (byte_stream_empty(bs) < 1) - return 0; /* XXX throw an exception */ + g_return_val_if_fail(byte_stream_bytes_left(bs) >= 1, 0); bs->offset++; - return aimutil_getle8(bs->data + bs->offset - 1); } guint16 byte_stream_getle16(ByteStream *bs) { - - if (byte_stream_empty(bs) < 2) - return 0; /* XXX throw an exception */ + g_return_val_if_fail(byte_stream_bytes_left(bs) >= 2, 0); bs->offset += 2; - return aimutil_getle16(bs->data + bs->offset - 2); } guint32 byte_stream_getle32(ByteStream *bs) { - - if (byte_stream_empty(bs) < 4) - return 0; /* XXX throw an exception */ + g_return_val_if_fail(byte_stream_bytes_left(bs) >= 4, 0); bs->offset += 4; - return aimutil_getle32(bs->data + bs->offset - 4); } @@ -169,9 +140,7 @@ int byte_stream_getrawbuf(ByteStream *bs, guint8 *buf, int len) { - - if (byte_stream_empty(bs) < len) - return 0; + g_return_val_if_fail(byte_stream_bytes_left(bs) >= len, 0); byte_stream_getrawbuf_nocheck(bs, buf, len); return len; @@ -181,13 +150,10 @@ { guint8 *ob; - if (byte_stream_empty(bs) < len) - return NULL; + g_return_val_if_fail(byte_stream_bytes_left(bs) >= len, NULL); ob = g_malloc(len); - byte_stream_getrawbuf_nocheck(bs, ob, len); - return ob; } @@ -195,94 +161,69 @@ { char *ob; - if (byte_stream_empty(bs) < len) - return NULL; + g_return_val_if_fail(byte_stream_bytes_left(bs) >= len, NULL); ob = g_malloc(len + 1); - byte_stream_getrawbuf_nocheck(bs, (guint8 *)ob, len); - ob[len] = '\0'; - return ob; } int byte_stream_put8(ByteStream *bs, guint8 v) { - - if (byte_stream_empty(bs) < 1) - return 0; /* XXX throw an exception */ + g_return_val_if_fail(byte_stream_bytes_left(bs) >= 1, 0); bs->offset += aimutil_put8(bs->data + bs->offset, v); - return 1; } int byte_stream_put16(ByteStream *bs, guint16 v) { - - if (byte_stream_empty(bs) < 2) - return 0; /* XXX throw an exception */ + g_return_val_if_fail(byte_stream_bytes_left(bs) >= 2, 0); bs->offset += aimutil_put16(bs->data + bs->offset, v); - return 2; } int byte_stream_put32(ByteStream *bs, guint32 v) { - - if (byte_stream_empty(bs) < 4) - return 0; /* XXX throw an exception */ + g_return_val_if_fail(byte_stream_bytes_left(bs) >= 4, 0); bs->offset += aimutil_put32(bs->data + bs->offset, v); - return 1; } int byte_stream_putle8(ByteStream *bs, guint8 v) { - - if (byte_stream_empty(bs) < 1) - return 0; /* XXX throw an exception */ + g_return_val_if_fail(byte_stream_bytes_left(bs) >= 1, 0); bs->offset += aimutil_putle8(bs->data + bs->offset, v); - return 1; } int byte_stream_putle16(ByteStream *bs, guint16 v) { - - if (byte_stream_empty(bs) < 2) - return 0; /* XXX throw an exception */ + g_return_val_if_fail(byte_stream_bytes_left(bs) >= 2, 0); bs->offset += aimutil_putle16(bs->data + bs->offset, v); - return 2; } int byte_stream_putle32(ByteStream *bs, guint32 v) { - - if (byte_stream_empty(bs) < 4) - return 0; /* XXX throw an exception */ + g_return_val_if_fail(byte_stream_bytes_left(bs) >= 4, 0); bs->offset += aimutil_putle32(bs->data + bs->offset, v); - return 1; } int byte_stream_putraw(ByteStream *bs, const guint8 *v, int len) { - - if (byte_stream_empty(bs) < len) - return 0; /* XXX throw an exception */ + g_return_val_if_fail(byte_stream_bytes_left(bs) >= len, 0); memcpy(bs->data + bs->offset, v, len); bs->offset += len; - return len; } @@ -293,17 +234,12 @@ int byte_stream_putbs(ByteStream *bs, ByteStream *srcbs, int len) { - - if (byte_stream_empty(srcbs) < len) - return 0; /* XXX throw exception (underrun) */ - - if (byte_stream_empty(bs) < len) - return 0; /* XXX throw exception (overflow) */ + g_return_val_if_fail(byte_stream_bytes_left(srcbs) >= len, 0); + g_return_val_if_fail(byte_stream_bytes_left(bs) >= len, 0); memcpy(bs->data + bs->offset, srcbs->data + srcbs->offset, len); bs->offset += len; srcbs->offset += len; - return len; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/oscar/encoding.c Thu Jul 29 00:06:56 2010 +0000 @@ -0,0 +1,228 @@ +/* + * Purple's oscar protocol plugin + * This file is the legal property of its developers. + * Please see the AUTHORS file distributed alongside this file. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA +*/ + +#include "encoding.h" + +guint16 +oscar_charset_check(const char *utf8) +{ + while (*utf8++) + { + if ((unsigned char)(*utf8) > 0x7f) { + /* not ASCII! */ + return AIM_CHARSET_UNICODE; + } + } + return AIM_CHARSET_ASCII; +} + +static gchar * +encoding_extract(const char *encoding) +{ + char *begin, *end; + + if (encoding == NULL) { + return NULL; + } + + if (!g_str_has_prefix(encoding, "text/aolrtf; charset=") && + !g_str_has_prefix(encoding, "text/x-aolrtf; charset=") && + !g_str_has_prefix(encoding, "text/plain; charset=")) { + return g_strdup(encoding); + } + + begin = strchr(encoding, '"'); + end = strrchr(encoding, '"'); + + if ((begin == NULL) || (end == NULL) || (begin >= end)) { + return g_strdup(encoding); + } + + return g_strndup(begin+1, (end-1) - begin); +} + +gchar * +oscar_encoding_to_utf8(const char *encoding, const char *text, int textlen) +{ + gchar *utf8 = NULL; + const gchar *glib_encoding = NULL; + gchar *extracted_encoding = encoding_extract(encoding); + + if (extracted_encoding == NULL || *extracted_encoding == '\0') { + purple_debug_info("oscar", "Empty encoding, assuming UTF-8\n"); + } else if (!g_ascii_strcasecmp(extracted_encoding, "iso-8859-1")) { + glib_encoding = "iso-8859-1"; + } else if (!g_ascii_strcasecmp(extracted_encoding, "ISO-8859-1-Windows-3.1-Latin-1") || !g_ascii_strcasecmp(extracted_encoding, "us-ascii")) { + glib_encoding = "Windows-1252"; + } else if (!g_ascii_strcasecmp(extracted_encoding, "unicode-2-0")) { + glib_encoding = "UTF-16BE"; + } else if (g_ascii_strcasecmp(extracted_encoding, "utf-8")) { + purple_debug_warning("oscar", "Unrecognized character encoding \"%s\", attempting to convert to UTF-8 anyway\n", extracted_encoding); + glib_encoding = extracted_encoding; + } + + if (glib_encoding != NULL) { + utf8 = g_convert(text, textlen, "UTF-8", glib_encoding, NULL, NULL, NULL); + } + + /* + * If utf8 is still NULL then either the encoding is utf-8 or + * we have been unable to convert the text to utf-8 from the encoding + * that was specified. So we check if the text is valid utf-8 then + * just copy it. + */ + if (utf8 == NULL) { + if (textlen != 0 && *text != '\0' && !g_utf8_validate(text, textlen, NULL)) + utf8 = g_strdup(_("(There was an error receiving this message. The buddy you are speaking with is probably using a different encoding than expected. If you know what encoding he is using, you can specify it in the advanced account options for your AIM/ICQ account.)")); + else + utf8 = g_strndup(text, textlen); + } + + g_free(extracted_encoding); + return utf8; +} + +gchar * +oscar_utf8_try_convert(PurpleAccount *account, OscarData *od, const gchar *msg) +{ + const char *charset = NULL; + char *ret = NULL; + + if (od->icq) + charset = purple_account_get_string(account, "encoding", NULL); + + if(charset && *charset) + ret = g_convert(msg, -1, "UTF-8", charset, NULL, NULL, NULL); + + if(!ret) + ret = purple_utf8_try_convert(msg); + + return ret; +} + +static gchar * +oscar_convert_to_utf8(const gchar *data, gsize datalen, const char *charsetstr, gboolean fallback) +{ + gchar *ret = NULL; + GError *err = NULL; + + if ((charsetstr == NULL) || (*charsetstr == '\0')) + return NULL; + + if (g_ascii_strcasecmp("UTF-8", charsetstr)) { + if (fallback) + ret = g_convert_with_fallback(data, datalen, "UTF-8", charsetstr, "?", NULL, NULL, &err); + else + ret = g_convert(data, datalen, "UTF-8", charsetstr, NULL, NULL, &err); + if (err != NULL) { + purple_debug_warning("oscar", "Conversion from %s failed: %s.\n", + charsetstr, err->message); + g_error_free(err); + } + } else { + if (g_utf8_validate(data, datalen, NULL)) + ret = g_strndup(data, datalen); + else + purple_debug_warning("oscar", "String is not valid UTF-8.\n"); + } + + return ret; +} + +gchar * +oscar_decode_im(PurpleAccount *account, const char *sourcebn, guint16 charset, const gchar *data, gsize datalen) +{ + gchar *ret = NULL; + /* charsetstr1 is always set to what the correct encoding should be. */ + const gchar *charsetstr1, *charsetstr2, *charsetstr3 = NULL; + + if ((datalen == 0) || (data == NULL)) + return NULL; + + if (charset == AIM_CHARSET_UNICODE) { + charsetstr1 = "UTF-16BE"; + charsetstr2 = "UTF-8"; + } else if (charset == AIM_CHARSET_LATIN_1) { + if ((sourcebn != NULL) && oscar_util_valid_name_icq(sourcebn)) + charsetstr1 = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING); + else + charsetstr1 = "ISO-8859-1"; + charsetstr2 = "UTF-8"; + } else if (charset == AIM_CHARSET_ASCII) { + /* Should just be "ASCII" */ + charsetstr1 = "ASCII"; + charsetstr2 = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING); + } else if (charset == 0x000d) { + /* iChat sending unicode over a Direct IM connection = UTF-8 */ + /* Mobile AIM client on multiple devices (including Blackberry Tour, Nokia 3100, and LG VX6000) = ISO-8859-1 */ + charsetstr1 = "UTF-8"; + charsetstr2 = "ISO-8859-1"; + charsetstr3 = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING); + } else { + /* Unknown, hope for valid UTF-8... */ + charsetstr1 = "UTF-8"; + charsetstr2 = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING); + } + + purple_debug_info("oscar", "Parsing IM, charset=0x%04hx, datalen=%" G_GSIZE_FORMAT ", choice1=%s, choice2=%s, choice3=%s\n", + charset, datalen, charsetstr1, charsetstr2, (charsetstr3 ? charsetstr3 : "")); + + ret = oscar_convert_to_utf8(data, datalen, charsetstr1, FALSE); + if (ret == NULL) { + if (charsetstr3 != NULL) { + /* Try charsetstr2 without allowing substitutions, then fall through to charsetstr3 if needed */ + ret = oscar_convert_to_utf8(data, datalen, charsetstr2, FALSE); + if (ret == NULL) + ret = oscar_convert_to_utf8(data, datalen, charsetstr3, TRUE); + } else { + /* Try charsetstr2, allowing substitutions */ + ret = oscar_convert_to_utf8(data, datalen, charsetstr2, TRUE); + } + } + if (ret == NULL) { + char *str, *salvage, *tmp; + + str = g_malloc(datalen + 1); + strncpy(str, data, datalen); + str[datalen] = '\0'; + salvage = purple_utf8_salvage(str); + tmp = g_strdup_printf(_("(There was an error receiving this message. Either you and %s have different encodings selected, or %s has a buggy client.)"), + sourcebn, sourcebn); + ret = g_strdup_printf("%s %s", salvage, tmp); + g_free(tmp); + g_free(str); + g_free(salvage); + } + + return ret; +} + +gchar * +oscar_convert_to_best_encoding(const gchar *msg, gsize *result_len, guint16 *charset, gchar **charsetstr) +{ + guint16 msg_charset = oscar_charset_check(msg); + if (charset != NULL) { + *charset = msg_charset; + } + if (charsetstr != NULL) { + *charsetstr = msg_charset == AIM_CHARSET_ASCII ? "us-ascii" : "unicode-2-0"; + } + return g_convert(msg, -1, msg_charset == AIM_CHARSET_ASCII ? "ASCII" : "UTF-16BE", "UTF-8", NULL, result_len, NULL); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/oscar/encoding.h Thu Jul 29 00:06:56 2010 +0000 @@ -0,0 +1,51 @@ +/* + * Purple's oscar protocol plugin + * This file is the legal property of its developers. + * Please see the AUTHORS file distributed alongside this file. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA +*/ + +#ifndef _ENCODING_H_ +#define _ENCODING_H_ + +#include "oscar.h" +#include "oscarcommon.h" + +/** + * Determine the simplest encoding we can send this message in. + */ +guint16 oscar_charset_check(const char *utf8); + +gchar * oscar_encoding_to_utf8(const char *encoding, const char *text, int textlen); +gchar * oscar_utf8_try_convert(PurpleAccount *account, OscarData *od, const gchar *msg); + +/** + * This attemps to decode an incoming IM into a UTF8 string. + * + * We try decoding using two different character sets. The charset + * specified in the IM determines the order in which we attempt to + * decode. We do this because there are lots of broken ICQ clients + * that don't correctly send non-ASCII messages. And if Purple isn't + * able to deal with that crap, then people complain like banshees. + */ +gchar * oscar_decode_im(PurpleAccount *account, const char *sourcebn, guint16 charset, const gchar *data, gsize datalen); + +/** + * Figure out what encoding to use when sending a given outgoing message. + */ +gchar * oscar_convert_to_best_encoding(const gchar *msg, gsize *result_len, guint16 *charset, gchar **charsetstr); + +#endif \ No newline at end of file
--- a/libpurple/protocols/oscar/family_admin.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/family_admin.c Thu Jul 29 00:06:56 2010 +0000 @@ -68,7 +68,7 @@ perms = byte_stream_get16(bs); tlvcount = byte_stream_get16(bs); - while (tlvcount && byte_stream_empty(bs)) { + while (tlvcount && byte_stream_bytes_left(bs)) { guint16 type, length; type = byte_stream_get16(bs);
--- a/libpurple/protocols/oscar/family_advert.c Thu Jul 08 17:00:45 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * Purple's oscar protocol plugin - * This file is the legal property of its developers. - * Please see the AUTHORS file distributed alongside this file. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA -*/ - -/* - * Family 0x0005 - Advertisements. - * - */ - -#include "oscar.h" - -void -aim_ads_requestads(OscarData *od, FlapConnection *conn) -{ - aim_genericreq_n(od, conn, SNAC_FAMILY_ADVERT, 0x0002); -} - -static int snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs) -{ - return 0; -} - -int adverts_modfirst(OscarData *od, aim_module_t *mod) -{ - - mod->family = SNAC_FAMILY_ADVERT; - mod->version = 0x0001; - mod->toolid = 0x0001; - mod->toolversion = 0x0001; - mod->flags = 0; - strncpy(mod->name, "advert", sizeof(mod->name)); - mod->snachandler = snachandler; - - return 0; -}
--- a/libpurple/protocols/oscar/family_auth.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/family_auth.c Thu Jul 29 00:06:56 2010 +0000 @@ -56,17 +56,10 @@ aim_encode_password(const char *password, guint8 *encoded) { guint8 encoding_table[] = { -#if 0 /* old v1 table */ - 0xf3, 0xb3, 0x6c, 0x99, - 0x95, 0x3f, 0xac, 0xb6, - 0xc5, 0xfa, 0x6b, 0x63, - 0x69, 0x6c, 0xc3, 0x9f -#else /* v2.1 table, also works for ICQ */ 0xf3, 0x26, 0x81, 0xc4, 0x39, 0x86, 0xdb, 0x92, 0x71, 0xa3, 0xb9, 0xe6, 0x53, 0x7a, 0x95, 0x7c -#endif }; unsigned int i; @@ -385,12 +378,6 @@ if (aim_tlv_gettlv(tlvlist, 0x0043, 1)) info->latestbeta.name = aim_tlv_getstr(tlvlist, 0x0043, 1); -#if 0 - if (aim_tlv_gettlv(tlvlist, 0x0048, 1)) { - /* beta serial */ - } -#endif - if (aim_tlv_gettlv(tlvlist, 0x0044, 1)) info->latestrelease.build = aim_tlv_get32(tlvlist, 0x0044, 1); if (aim_tlv_gettlv(tlvlist, 0x0045, 1)) @@ -400,27 +387,12 @@ if (aim_tlv_gettlv(tlvlist, 0x0047, 1)) info->latestrelease.name = aim_tlv_getstr(tlvlist, 0x0047, 1); -#if 0 - if (aim_tlv_gettlv(tlvlist, 0x0049, 1)) { - /* lastest release serial */ - } -#endif - /* * URL to change password. */ if (aim_tlv_gettlv(tlvlist, 0x0054, 1)) info->chpassurl = aim_tlv_getstr(tlvlist, 0x0054, 1); -#if 0 - /* - * Unknown. Seen on an @mac.com username with value of 0x003f - */ - if (aim_tlv_gettlv(tlvlist, 0x0055, 1)) { - /* Unhandled */ - } -#endif - od->authinfo = info; if ((userfunc = aim_callhandler(od, snac ? snac->family : SNAC_FAMILY_AUTH, snac ? snac->subtype : 0x0003)))
--- a/libpurple/protocols/oscar/family_bos.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/family_bos.c Thu Jul 29 00:06:56 2010 +0000 @@ -68,98 +68,6 @@ return ret; } -/* - * Subtype 0x0004 - Set group permission mask. - * - * Normally 0x1f (all classes). - * - * The group permission mask allows you to keep users of a certain - * class or classes from talking to you. The mask should be - * a bitwise OR of all the user classes you want to see you. - * - */ -void -aim_bos_setgroupperm(OscarData *od, FlapConnection *conn, guint32 mask) -{ - aim_genericreq_l(od, conn, SNAC_FAMILY_BOS, 0x0004, &mask); -} - -/* - * Stubtypes 0x0005, 0x0006, 0x0007, and 0x0008 - Modify permit/deny lists. - * - * Changes your visibility depending on changetype: - * - * AIM_VISIBILITYCHANGE_PERMITADD: Lets provided list of names see you - * AIM_VISIBILITYCHANGE_PERMIDREMOVE: Removes listed names from permit list - * AIM_VISIBILITYCHANGE_DENYADD: Hides you from provided list of names - * AIM_VISIBILITYCHANGE_DENYREMOVE: Lets list see you again - * - * list should be a list of "Buddy Name One&BuddyNameTwo&" etc. - * - * Equivelents to options in WinAIM: - * - Allow all users to contact me: Send an AIM_VISIBILITYCHANGE_DENYADD - * with only your name on it. - * - Allow only users on my Buddy List: Send an - * AIM_VISIBILITYCHANGE_PERMITADD with the list the same as your - * buddy list - * - Allow only the uesrs below: Send an AIM_VISIBILITYCHANGE_PERMITADD - * with everyone listed that you want to see you. - * - Block all users: Send an AIM_VISIBILITYCHANGE_PERMITADD with only - * yourself in the list - * - Block the users below: Send an AIM_VISIBILITYCHANGE_DENYADD with - * the list of users to be blocked - * - * XXX ye gods. - */ -int aim_bos_changevisibility(OscarData *od, FlapConnection *conn, int changetype, const char *denylist) -{ - ByteStream bs; - int packlen = 0; - guint16 subtype; - char *localcpy = NULL, *tmpptr = NULL; - int i; - int listcount; - aim_snacid_t snacid; - - if (!denylist) - return -EINVAL; - - if (changetype == AIM_VISIBILITYCHANGE_PERMITADD) - subtype = 0x05; - else if (changetype == AIM_VISIBILITYCHANGE_PERMITREMOVE) - subtype = 0x06; - else if (changetype == AIM_VISIBILITYCHANGE_DENYADD) - subtype = 0x07; - else if (changetype == AIM_VISIBILITYCHANGE_DENYREMOVE) - subtype = 0x08; - else - return -EINVAL; - - localcpy = g_strdup(denylist); - - listcount = aimutil_itemcnt(localcpy, '&'); - packlen = aimutil_tokslen(localcpy, 99, '&') + listcount-1; - - byte_stream_new(&bs, packlen); - - for (i = 0; (i < (listcount - 1)) && (i < 99); i++) { - tmpptr = aimutil_itemindex(localcpy, i, '&'); - - byte_stream_put8(&bs, strlen(tmpptr)); - byte_stream_putstr(&bs, tmpptr); - - g_free(tmpptr); - } - g_free(localcpy); - - snacid = aim_cachesnac(od, SNAC_FAMILY_BOS, subtype, 0x0000, NULL, 0); - flap_connection_send_snac(od, conn, SNAC_FAMILY_BOS, subtype, 0x0000, snacid, &bs); - - byte_stream_destroy(&bs); - - return 0; -} - static int snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) {
--- a/libpurple/protocols/oscar/family_buddy.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/family_buddy.c Thu Jul 29 00:06:56 2010 +0000 @@ -88,117 +88,6 @@ } /* - * Subtype 0x0004 (SNAC_SUBTYPE_BUDDY_ADDBUDDY) - Add buddy to list. - * - * Adds a single buddy to your buddy list after login. - * XXX This should just be an extension of setbuddylist() - * - */ -int -aim_buddylist_addbuddy(OscarData *od, FlapConnection *conn, const char *sn) -{ - ByteStream bs; - aim_snacid_t snacid; - - if (!sn || !strlen(sn)) - return -EINVAL; - - byte_stream_new(&bs, 1+strlen(sn)); - - byte_stream_put8(&bs, strlen(sn)); - byte_stream_putstr(&bs, sn); - - snacid = aim_cachesnac(od, SNAC_FAMILY_BUDDY, 0x0004, 0x0000, sn, strlen(sn)+1); - flap_connection_send_snac(od, conn, SNAC_FAMILY_BUDDY, 0x0004, 0x0000, snacid, &bs); - - byte_stream_destroy(&bs); - - return 0; -} - -/* - * Subtype 0x0004 (SNAC_SUBTYPE_BUDDY_ADDBUDDY) - Add multiple buddies to your buddy list. - * - * This just builds the "set buddy list" command then queues it. - * - * buddy_list = "Buddy Name One&BuddyNameTwo&"; - * - * XXX Clean this up. - * - */ -int -aim_buddylist_set(OscarData *od, FlapConnection *conn, const char *buddy_list) -{ - ByteStream bs; - aim_snacid_t snacid; - int len = 0; - char *localcpy = NULL; - char *tmpptr = NULL; - - if (!buddy_list || !(localcpy = g_strdup(buddy_list))) - return -EINVAL; - - for (tmpptr = strtok(localcpy, "&"); tmpptr; ) { - purple_debug_misc("oscar", "---adding: %s (%" G_GSIZE_FORMAT - ")\n", tmpptr, strlen(tmpptr)); - len += 1 + strlen(tmpptr); - tmpptr = strtok(NULL, "&"); - } - - byte_stream_new(&bs, len); - - strncpy(localcpy, buddy_list, strlen(buddy_list) + 1); - - for (tmpptr = strtok(localcpy, "&"); tmpptr; ) { - - purple_debug_misc("oscar", "---adding: %s (%" G_GSIZE_FORMAT - ")\n", tmpptr, strlen(tmpptr)); - - byte_stream_put8(&bs, strlen(tmpptr)); - byte_stream_putstr(&bs, tmpptr); - tmpptr = strtok(NULL, "&"); - } - - snacid = aim_cachesnac(od, SNAC_FAMILY_BUDDY, 0x0004, 0x0000, NULL, 0); - flap_connection_send_snac(od, conn, SNAC_FAMILY_BUDDY, 0x0004, 0x0000, snacid, &bs); - - byte_stream_destroy(&bs); - - g_free(localcpy); - - return 0; -} - -/* - * Subtype 0x0005 (SNAC_SUBTYPE_BUDDY_REMBUDDY) - Remove buddy from list. - * - * XXX generalise to support removing multiple buddies (basically, its - * the same as setbuddylist() but with a different snac subtype). - * - */ -int -aim_buddylist_removebuddy(OscarData *od, FlapConnection *conn, const char *sn) -{ - ByteStream bs; - aim_snacid_t snacid; - - if (!sn || !strlen(sn)) - return -EINVAL; - - byte_stream_new(&bs, 1 + strlen(sn)); - - byte_stream_put8(&bs, strlen(sn)); - byte_stream_putstr(&bs, sn); - - snacid = aim_cachesnac(od, SNAC_FAMILY_BUDDY, 0x0005, 0x0000, sn, strlen(sn)+1); - flap_connection_send_snac(od, conn, SNAC_FAMILY_BUDDY, 0x0005, 0x0000, snacid, &bs); - - byte_stream_destroy(&bs); - - return 0; -} - -/* * Subtypes 0x000b (SNAC_SUBTYPE_BUDDY_ONCOMING) and 0x000c (SNAC_SUBTYPE_BUDDY_OFFGOING) - Change in buddy status * * Oncoming Buddy notifications contain a subset of the
--- a/libpurple/protocols/oscar/family_chat.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/family_chat.c Thu Jul 29 00:06:56 2010 +0000 @@ -47,74 +47,6 @@ return; } -char * -aim_chat_getname(FlapConnection *conn) -{ - struct chatconnpriv *ccp; - - if (!conn) - return NULL; - - if (conn->type != SNAC_FAMILY_CHAT) - return NULL; - - ccp = (struct chatconnpriv *)conn->internal; - - return ccp->name; -} - -/* XXX get this into conn.c -- evil!! */ -FlapConnection * -aim_chat_getconn(OscarData *od, const char *name) -{ - GSList *cur; - - for (cur = od->oscar_connections; cur; cur = cur->next) - { - FlapConnection *conn; - struct chatconnpriv *ccp; - - conn = cur->data; - ccp = (struct chatconnpriv *)conn->internal; - - if (conn->type != SNAC_FAMILY_CHAT) - continue; - if (!conn->internal) - { - purple_debug_misc("oscar", "%sfaim: chat: chat connection with no name! (fd = %d)\n", - conn->gsc ? "(ssl) " : "", conn->gsc ? conn->gsc->fd : conn->fd); - continue; - } - - if (strcmp(ccp->name, name) == 0) - return conn; - } - - return NULL; -} - -int -aim_chat_attachname(FlapConnection *conn, guint16 exchange, const char *roomname, guint16 instance) -{ - struct chatconnpriv *ccp; - - if (!conn || !roomname) - return -EINVAL; - - if (conn->internal) - g_free(conn->internal); - - ccp = g_new(struct chatconnpriv, 1); - - ccp->exchange = exchange; - ccp->name = g_strdup(roomname); - ccp->instance = instance; - - conn->internal = (void *)ccp; - - return 0; -} - int aim_chat_readroominfo(ByteStream *bs, struct aim_chat_roominfo *outinfo) { @@ -129,19 +61,6 @@ return 0; } -int -aim_chat_leaveroom(OscarData *od, const char *name) -{ - FlapConnection *conn; - - if (!(conn = aim_chat_getconn(od, name))) - return -ENOENT; - - flap_connection_close(od, conn); - - return 0; -} - /* * Subtype 0x0002 - General room information. Lots of stuff. * @@ -153,21 +72,12 @@ static int infoupdate(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - aim_userinfo_t *userinfo = NULL; aim_rxcallback_t userfunc; int ret = 0; - int usercount; guint8 detaillevel = 0; - char *roomname; struct aim_chat_roominfo roominfo; - guint16 tlvcount = 0; GSList *tlvlist; - aim_tlv_t *tlv; - char *roomdesc; - guint16 flags; - guint32 creationtime; guint16 maxmsglen, maxvisiblemsglen; - guint16 unknown_d2, unknown_d5; aim_chat_readroominfo(bs, &roominfo); @@ -178,139 +88,27 @@ return 1; } - tlvcount = byte_stream_get16(bs); - /* * Everything else are TLVs. */ tlvlist = aim_tlvlist_read(bs); /* - * TLV type 0x006a is the room name in Human Readable Form. - */ - roomname = aim_tlv_getstr(tlvlist, 0x006a, 1); - - /* - * Type 0x006f: Number of occupants. - */ - usercount = aim_tlv_get16(tlvlist, 0x006f, 1); - - /* - * Type 0x0073: Occupant list. - */ - tlv = aim_tlv_gettlv(tlvlist, 0x0073, 1); - if (tlv != NULL) - { - int curoccupant = 0; - ByteStream occbs; - - /* Allocate enough userinfo structs for all occupants */ - userinfo = g_new0(aim_userinfo_t, usercount); - - byte_stream_init(&occbs, tlv->value, tlv->length); - - while (curoccupant < usercount) - aim_info_extract(od, &occbs, &userinfo[curoccupant++]); - } - - /* - * Type 0x00c9: Flags. (AIM_CHATROOM_FLAG) - */ - flags = aim_tlv_get16(tlvlist, 0x00c9, 1); - - /* - * Type 0x00ca: Creation time (4 bytes) - */ - creationtime = aim_tlv_get32(tlvlist, 0x00ca, 1); - - /* * Type 0x00d1: Maximum Message Length */ maxmsglen = aim_tlv_get16(tlvlist, 0x00d1, 1); /* - * Type 0x00d2: Unknown. (2 bytes) - */ - unknown_d2 = aim_tlv_get16(tlvlist, 0x00d2, 1); - - /* - * Type 0x00d3: Room Description - */ - roomdesc = aim_tlv_getstr(tlvlist, 0x00d3, 1); - -#if 0 - /* - * Type 0x000d4: Unknown (flag only) - */ - if (aim_tlv_gettlv(tlvlist, 0x000d4, 1)) { - /* Unhandled */ - } -#endif - - /* - * Type 0x00d5: Unknown. (1 byte) - */ - unknown_d5 = aim_tlv_get8(tlvlist, 0x00d5, 1); - -#if 0 - /* - * Type 0x00d6: Encoding 1 ("us-ascii") - */ - if (aim_tlv_gettlv(tlvlist, 0x000d6, 1)) { - /* Unhandled */ - } - - /* - * Type 0x00d7: Language 1 ("en") - */ - if (aim_tlv_gettlv(tlvlist, 0x000d7, 1)) { - /* Unhandled */ - } - - /* - * Type 0x00d8: Encoding 2 ("us-ascii") - */ - if (aim_tlv_gettlv(tlvlist, 0x000d8, 1)) { - /* Unhandled */ - } - - /* - * Type 0x00d9: Language 2 ("en") - */ - if (aim_tlv_gettlv(tlvlist, 0x000d9, 1)) { - /* Unhandled */ - } -#endif - - /* * Type 0x00da: Maximum visible message length */ maxvisiblemsglen = aim_tlv_get16(tlvlist, 0x00da, 1); if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) { - ret = userfunc(od, conn, - frame, - &roominfo, - roomname, - usercount, - userinfo, - roomdesc, - flags, - creationtime, - maxmsglen, - unknown_d2, - unknown_d5, - maxvisiblemsglen); + ret = userfunc(od, conn, frame, maxmsglen, maxvisiblemsglen); } g_free(roominfo.name); - while (usercount > 0) - aim_info_free(&userinfo[--usercount]); - - g_free(userinfo); - g_free(roomname); - g_free(roomdesc); aim_tlvlist_free(tlvlist); return ret; @@ -324,7 +122,7 @@ aim_rxcallback_t userfunc; int curcount = 0, ret = 0; - while (byte_stream_empty(bs)) { + while (byte_stream_bytes_left(bs)) { curcount++; userinfo = g_realloc(userinfo, curcount * sizeof(aim_userinfo_t)); aim_info_extract(od, bs, &userinfo[curcount-1]); @@ -523,16 +321,6 @@ aim_info_extract(od, &tbs, &userinfo); } -#if 0 - /* - * Type 0x0001: If present, it means it was a message to the - * room (as opposed to a whisper). - */ - if (aim_tlv_gettlv(tlvlist, 0x0001, 1)) { - /* Unhandled */ - } -#endif - /* * Type 0x0005: Message Block. Conains more TLVs. */
--- a/libpurple/protocols/oscar/family_chatnav.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/family_chatnav.c Thu Jul 29 00:06:56 2010 +0000 @@ -185,32 +185,6 @@ exchanges[curexchange-1].number = byte_stream_get16(&tbs); innerlist = aim_tlvlist_read(&tbs); -#if 0 - /* - * Type 0x000a: Unknown. - * - * Usually three bytes: 0x0114 (exchange 1) or 0x010f (others). - * - */ - if (aim_tlv_gettlv(innerlist, 0x000a, 1)) { - /* Unhandled */ - } - - /* - * Type 0x000d: Unknown. - */ - if (aim_tlv_gettlv(innerlist, 0x000d, 1)) { - /* Unhandled */ - } - - /* - * Type 0x0004: Unknown - */ - if (aim_tlv_gettlv(innerlist, 0x0004, 1)) { - /* Unhandled */ - } -#endif - /* * Type 0x0002: Unknown */ @@ -234,36 +208,6 @@ if (aim_tlv_gettlv(innerlist, 0x00c9, 1)) exchanges[curexchange-1].flags = aim_tlv_get16(innerlist, 0x00c9, 1); -#if 0 - /* - * Type 0x00ca: Creation Date - */ - if (aim_tlv_gettlv(innerlist, 0x00ca, 1)) { - /* Unhandled */ - } - - /* - * Type 0x00d0: Mandatory Channels? - */ - if (aim_tlv_gettlv(innerlist, 0x00d0, 1)) { - /* Unhandled */ - } - - /* - * Type 0x00d1: Maximum Message length - */ - if (aim_tlv_gettlv(innerlist, 0x00d1, 1)) { - /* Unhandled */ - } - - /* - * Type 0x00d2: Maximum Occupancy? - */ - if (aim_tlv_gettlv(innerlist, 0x00d2, 1)) { - /* Unhandled */ - } -#endif - /* * Type 0x00d3: Exchange Description */ @@ -272,15 +216,6 @@ else exchanges[curexchange-1].name = NULL; -#if 0 - /* - * Type 0x00d4: Exchange Description URL - */ - if (aim_tlv_gettlv(innerlist, 0x00d4, 1)) { - /* Unhandled */ - } -#endif - /* * Type 0x00d5: Creation Permissions * @@ -327,15 +262,6 @@ else exchanges[curexchange-1].lang2 = NULL; -#if 0 - /* - * Type 0x00da: Unknown - */ - if (aim_tlv_gettlv(innerlist, 0x00da, 1)) { - /* Unhandled */ - } -#endif - aim_tlvlist_free(innerlist); }
--- a/libpurple/protocols/oscar/family_feedbag.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/family_feedbag.c Thu Jul 29 00:06:56 2010 +0000 @@ -1155,41 +1155,6 @@ } /* - * Subtype 0x0005 - Request SSI Data when you have a timestamp and revision - * number. - * - * The data will only be sent if it is newer than the posted local - * timestamp and revision. - * - * Note that the client should never increment the revision, only the server. - * - */ -int aim_ssi_reqifchanged(OscarData *od, time_t timestamp, guint16 numitems) -{ - FlapConnection *conn; - ByteStream bs; - aim_snacid_t snacid; - - if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG))) - return -EINVAL; - - byte_stream_new(&bs, 4+2); - - byte_stream_put32(&bs, timestamp); - byte_stream_put16(&bs, numitems); - - snacid = aim_cachesnac(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_REQIFCHANGED, 0x0000, NULL, 0); - flap_connection_send_snac(od, conn, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_REQIFCHANGED, 0x0000, snacid, &bs); - - byte_stream_destroy(&bs); - - /* Free any current data, just in case */ - aim_ssi_freelist(od); - - return 0; -} - -/* * Subtype 0x0006 - SSI Data. */ static int parsedata(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) @@ -1205,7 +1170,7 @@ od->ssi.numitems += byte_stream_get16(bs); /* # of items in this SSI SNAC */ /* Read in the list */ - while (byte_stream_empty(bs) > 4) { /* last four bytes are timestamp */ + while (byte_stream_bytes_left(bs) > 4) { /* last four bytes are timestamp */ if ((namelen = byte_stream_get16(bs))) name = byte_stream_getstr(bs, namelen); else @@ -1323,7 +1288,7 @@ guint16 len, gid, bid, type; GSList *data; - while (byte_stream_empty(bs)) { + while (byte_stream_bytes_left(bs)) { if ((len = byte_stream_get16(bs))) name = byte_stream_getstr(bs, len); else @@ -1361,7 +1326,7 @@ GSList *data; struct aim_ssi_item *item; - while (byte_stream_empty(bs)) { + while (byte_stream_bytes_left(bs)) { if ((len = byte_stream_get16(bs))) name = byte_stream_getstr(bs, len); else @@ -1413,7 +1378,7 @@ guint16 gid, bid; struct aim_ssi_item *del; - while (byte_stream_empty(bs)) { + while (byte_stream_bytes_left(bs)) { byte_stream_advance(bs, byte_stream_get16(bs)); gid = byte_stream_get16(bs); bid = byte_stream_get16(bs); @@ -1446,7 +1411,7 @@ /* Read in the success/failure flags from the ack SNAC */ cur = od->ssi.pending; - while (cur && (byte_stream_empty(bs)>0)) { + while (cur && (byte_stream_bytes_left(bs)>0)) { cur->ack = byte_stream_get16(bs); cur = cur->next; } @@ -1602,45 +1567,6 @@ } /* - * Subtype 0x0014 - Grant authorization - * - * Authorizes a contact so they can add you to their contact list. - * - */ -int aim_ssi_sendauth(OscarData *od, char *bn, char *msg) -{ - FlapConnection *conn; - ByteStream bs; - aim_snacid_t snacid; - - if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)) || !bn) - return -EINVAL; - - byte_stream_new(&bs, 1+strlen(bn) + 2+(msg ? strlen(msg)+1 : 0) + 2); - - /* Username */ - byte_stream_put8(&bs, strlen(bn)); - byte_stream_putstr(&bs, bn); - - /* Message (null terminated) */ - byte_stream_put16(&bs, msg ? strlen(msg) : 0); - if (msg) { - byte_stream_putstr(&bs, msg); - byte_stream_put8(&bs, 0x00); - } - - /* Unknown */ - byte_stream_put16(&bs, 0x0000); - - snacid = aim_cachesnac(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_SENDAUTH, 0x0000, NULL, 0); - flap_connection_send_snac(od, conn, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_SENDAUTH, 0x0000, snacid, &bs); - - byte_stream_destroy(&bs); - - return 0; -} - -/* * Subtype 0x0015 - Receive an authorization grant */ static int receiveauthgrant(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--- a/libpurple/protocols/oscar/family_icbm.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/family_icbm.c Thu Jul 29 00:06:56 2010 +0000 @@ -44,6 +44,7 @@ * Make sure flap_connection_findbygroup is used by all functions. */ +#include "encoding.h" #include "oscar.h" #include "peer.h" @@ -108,69 +109,6 @@ } /* - * Takes a msghdr (and a length) and returns a client type - * code. Note that this is *only a guess* and has a low likelihood - * of actually being accurate. - * - * Its based on experimental data, with the help of Eric Warmenhoven - * who seems to have collected a wide variety of different AIM clients. - * - * - * Heres the current collection: - * 0501 0003 0101 0101 01 AOL Mobile Communicator, WinAIM 1.0.414 - * 0501 0003 0101 0201 01 WinAIM 2.0.847, 2.1.1187, 3.0.1464, - * 4.3.2229, 4.4.2286 - * 0501 0004 0101 0102 0101 WinAIM 4.1.2010, libfaim (right here) - * 0501 0003 0101 02 WinAIM 5 - * 0501 0001 01 iChat x.x, mobile buddies - * 0501 0001 0101 01 AOL v6.0, CompuServe 2000 v6.0, any TOC client - * 0501 0002 0106 WinICQ 5.45.1.3777.85 - * - * Note that in this function, only the feature bytes are tested, since - * the rest will always be the same. - * - */ -guint16 aim_im_fingerprint(const guint8 *msghdr, int len) -{ - static const struct { - guint16 clientid; - int len; - guint8 data[10]; - } fingerprints[] = { - /* AOL Mobile Communicator, WinAIM 1.0.414 */ - { AIM_CLIENTTYPE_MC, - 3, {0x01, 0x01, 0x01}}, - - /* WinAIM 2.0.847, 2.1.1187, 3.0.1464, 4.3.2229, 4.4.2286 */ - { AIM_CLIENTTYPE_WINAIM, - 3, {0x01, 0x01, 0x02}}, - - /* WinAIM 4.1.2010, libfaim */ - { AIM_CLIENTTYPE_WINAIM41, - 4, {0x01, 0x01, 0x01, 0x02}}, - - /* AOL v6.0, CompuServe 2000 v6.0, any TOC client */ - { AIM_CLIENTTYPE_AOL_TOC, - 1, {0x01}}, - - { 0, 0, {0x00}} - }; - int i; - - if (!msghdr || (len <= 0)) - return AIM_CLIENTTYPE_UNKNOWN; - - for (i = 0; fingerprints[i].len; i++) { - if (fingerprints[i].len != len) - continue; - if (memcmp(fingerprints[i].data, msghdr, fingerprints[i].len) == 0) - return fingerprints[i].clientid; - } - - return AIM_CLIENTTYPE_UNKNOWN; -} - -/* * Subtype 0x0001 - Error */ static int @@ -348,40 +286,14 @@ * * Possible flags: * AIM_IMFLAGS_AWAY -- Marks the message as an autoresponse - * AIM_IMFLAGS_ACK -- Requests that the server send an ack - * when the message is received (of type SNAC_FAMILY_ICBM/0x000c) * AIM_IMFLAGS_OFFLINE--If destination is offline, store it until they are * online (probably ICQ only). * - * Generally, you should use the lowest encoding possible to send - * your message. If you only use basic punctuation and the generic - * Latin alphabet, use ASCII7 (no flags). If you happen to use non-ASCII7 - * characters, but they are all clearly defined in ISO-8859-1, then - * use that. Keep in mind that not all characters in the PC ASCII8 - * character set are defined in the ISO standard. For those cases (most - * notably when the (r) symbol is used), you must use the full UNICODE - * encoding for your message. In UNICODE mode, _all_ characters must - * occupy 16bits, including ones that are not special. (Remember that - * the first 128 UNICODE symbols are equivalent to ASCII7, however they - * must be prefixed with a zero high order byte.) - * - * I strongly discourage the use of UNICODE mode, mainly because none - * of the clients I use can parse those messages (and besides that, - * wchars are difficult and non-portable to handle in most UNIX environments). - * If you really need to include special characters, use the HTML UNICODE - * entities. These are of the form ߪ where 2026 is the hex - * representation of the UNICODE index (in this case, UNICODE - * "Horizontal Ellipsis", or 133 in in ASCII8). - * * Implementation note: Since this is one of the most-used functions * in all of libfaim, it is written with performance in mind. As such, * it is not as clear as it could be in respect to how this message is * supposed to be layed out. Most obviously, tlvlists should be used * instead of writing out the bytes manually. - * - * XXX - more precise verification that we never send SNACs larger than 8192 - * XXX - check SNAC size for multipart - * */ int aim_im_sendch1_ext(OscarData *od, struct aim_sendimext_args *args) { @@ -390,7 +302,6 @@ ByteStream data; guchar cookie[8]; int msgtlvlen; - static const guint8 deffeatures[] = { 0x01, 0x01, 0x01, 0x02 }; if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM))) return -EINVAL; @@ -398,37 +309,17 @@ if (!args) return -EINVAL; - if (args->flags & AIM_IMFLAGS_MULTIPART) { - if (args->mpmsg->numparts == 0) - return -EINVAL; - } else { - if (!args->msg || (args->msglen <= 0)) - return -EINVAL; + if (!args->msg || (args->msglen <= 0)) + return -EINVAL; - if (args->msglen > MAXMSGLEN) - return -E2BIG; - } + if (args->msglen > MAXMSGLEN) + return -E2BIG; /* Painfully calculate the size of the message TLV */ msgtlvlen = 1 + 1; /* 0501 */ - - if (args->flags & AIM_IMFLAGS_CUSTOMFEATURES) - msgtlvlen += 2 + args->featureslen; - else - msgtlvlen += 2 + sizeof(deffeatures); - - if (args->flags & AIM_IMFLAGS_MULTIPART) { - aim_mpmsg_section_t *sec; - - for (sec = args->mpmsg->parts; sec; sec = sec->next) { - msgtlvlen += 2 /* 0101 */ + 2 /* block len */; - msgtlvlen += 4 /* charset */ + sec->datalen; - } - - } else { - msgtlvlen += 2 /* 0101 */ + 2 /* block len */; - msgtlvlen += 4 /* charset */ + args->msglen; - } + msgtlvlen += 2 + args->featureslen; + msgtlvlen += 2 /* 0101 */ + 2 /* block len */; + msgtlvlen += 4 /* charset */ + args->msglen; byte_stream_new(&data, msgtlvlen + 128); @@ -444,52 +335,31 @@ /* Features TLV (type 0x0501) */ byte_stream_put16(&data, 0x0501); - if (args->flags & AIM_IMFLAGS_CUSTOMFEATURES) { - byte_stream_put16(&data, args->featureslen); - byte_stream_putraw(&data, args->features, args->featureslen); - } else { - byte_stream_put16(&data, sizeof(deffeatures)); - byte_stream_putraw(&data, deffeatures, sizeof(deffeatures)); - } + byte_stream_put16(&data, args->featureslen); + byte_stream_putraw(&data, args->features, args->featureslen); - if (args->flags & AIM_IMFLAGS_MULTIPART) { - aim_mpmsg_section_t *sec; + /* Insert message text in a TLV (type 0x0101) */ + byte_stream_put16(&data, 0x0101); - /* Insert each message part in a TLV (type 0x0101) */ - for (sec = args->mpmsg->parts; sec; sec = sec->next) { - byte_stream_put16(&data, 0x0101); - byte_stream_put16(&data, sec->datalen + 4); - byte_stream_put16(&data, sec->charset); - byte_stream_put16(&data, sec->charsubset); - byte_stream_putraw(&data, (guchar *)sec->data, sec->datalen); - } - - } else { + /* Message block length */ + byte_stream_put16(&data, args->msglen + 0x04); - /* Insert message text in a TLV (type 0x0101) */ - byte_stream_put16(&data, 0x0101); - - /* Message block length */ - byte_stream_put16(&data, args->msglen + 0x04); + /* Character set */ + byte_stream_put16(&data, args->charset); + /* Character subset -- we always use 0 here */ + byte_stream_put16(&data, 0x0); - /* Character set */ - byte_stream_put16(&data, args->charset); - byte_stream_put16(&data, args->charsubset); - - /* Message. Not terminated */ - byte_stream_putraw(&data, (guchar *)args->msg, args->msglen); - } + /* Message. Not terminated */ + byte_stream_putraw(&data, (guchar *)args->msg, args->msglen); /* Set the Autoresponse flag */ if (args->flags & AIM_IMFLAGS_AWAY) { byte_stream_put16(&data, 0x0004); byte_stream_put16(&data, 0x0000); } else { - if (args->flags & AIM_IMFLAGS_ACK) { - /* Set the Request Acknowledge flag */ - byte_stream_put16(&data, 0x0003); - byte_stream_put16(&data, 0x0000); - } + /* Set the Request Acknowledge flag */ + byte_stream_put16(&data, 0x0003); + byte_stream_put16(&data, 0x0000); if (args->flags & AIM_IMFLAGS_OFFLINE) { /* Allow this message to be queued as an offline message */ @@ -534,33 +404,6 @@ } /* - * Simple wrapper for aim_im_sendch1_ext() - * - * You cannot use aim_send_im if you need the HASICON flag. You must - * use aim_im_sendch1_ext directly for that. - * - * aim_send_im also cannot be used if you require UNICODE messages, because - * that requires an explicit message length. Use aim_im_sendch1_ext(). - * - */ -int aim_im_sendch1(OscarData *od, const char *bn, guint16 flags, const char *msg) -{ - struct aim_sendimext_args args; - - args.destbn = bn; - args.flags = flags; - args.msg = msg; - args.msglen = strlen(msg); - args.charset = 0x0000; - args.charsubset = 0x0000; - - /* Make these don't get set by accident -- they need aim_im_sendch1_ext */ - args.flags &= ~(AIM_IMFLAGS_CUSTOMFEATURES | AIM_IMFLAGS_HASICON | AIM_IMFLAGS_MULTIPART); - - return aim_im_sendch1_ext(od, &args); -} - -/* * Subtype 0x0006 - Send a chat invitation. */ int aim_im_sendch2_chatinvite(OscarData *od, const char *bn, const char *msg, guint16 exchange, const char *roomname, guint16 instance) @@ -708,99 +551,6 @@ return 0; } -/* - * Subtype 0x0006 - Send a rich text message. - * - * This only works for ICQ 2001b (thats 2001 not 2000). Better, only - * send it to clients advertising the RTF capability. In fact, if you send - * it to a client that doesn't support that capability, the server will gladly - * bounce it back to you. - * - * You'd think this would be in icq.c, but, well, I'm trying to stick with - * the one-group-per-file scheme as much as possible. This could easily - * be an exception, since Rendezvous IMs are external of the Oscar core, - * and therefore are undefined. Really I just need to think of a good way to - * make an interface similar to what AOL actually uses. But I'm not using COM. - * - */ -int aim_im_sendch2_rtfmsg(OscarData *od, struct aim_sendrtfmsg_args *args) -{ - FlapConnection *conn; - ByteStream bs; - aim_snacid_t snacid; - guchar cookie[8]; - const char rtfcap[] = {"{97B12751-243C-4334-AD22-D6ABF73F1492}"}; /* OSCAR_CAPABILITY_ICQRTF capability in string form */ - int servdatalen; - - if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM))) - return -EINVAL; - - if (!args || !args->destbn || !args->rtfmsg) - return -EINVAL; - - servdatalen = 2+2+16+2+4+1+2 + 2+2+4+4+4 + 2+4+2+strlen(args->rtfmsg)+1 + 4+4+4+strlen(rtfcap)+1; - - aim_icbm_makecookie(cookie); - - byte_stream_new(&bs, 128+servdatalen); - - snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0); - - /* ICBM header */ - aim_im_puticbm(&bs, cookie, 0x0002, args->destbn); - - /* TLV t(0005) - Encompasses everything below. */ - byte_stream_put16(&bs, 0x0005); - byte_stream_put16(&bs, 2+8+16 + 2+2+2 + 2+2 + 2+2+servdatalen); - - byte_stream_put16(&bs, 0x0000); - byte_stream_putraw(&bs, cookie, 8); - byte_stream_putcaps(&bs, OSCAR_CAPABILITY_ICQSERVERRELAY); - - /* t(000a) l(0002) v(0001) */ - byte_stream_put16(&bs, 0x000a); - byte_stream_put16(&bs, 0x0002); - byte_stream_put16(&bs, 0x0001); - - /* t(000f) l(0000) v() */ - byte_stream_put16(&bs, 0x000f); - byte_stream_put16(&bs, 0x0000); - - /* Service Data TLV */ - byte_stream_put16(&bs, 0x2711); - byte_stream_put16(&bs, servdatalen); - - byte_stream_putle16(&bs, 11 + 16 /* 11 + (sizeof CLSID) */); - byte_stream_putle16(&bs, 9); - byte_stream_putcaps(&bs, OSCAR_CAPABILITY_EMPTY); - byte_stream_putle16(&bs, 0); - byte_stream_putle32(&bs, 0); - byte_stream_putle8(&bs, 0); - byte_stream_putle16(&bs, 0x03ea); /* trid1 */ - - byte_stream_putle16(&bs, 14); - byte_stream_putle16(&bs, 0x03eb); /* trid2 */ - byte_stream_putle32(&bs, 0); - byte_stream_putle32(&bs, 0); - byte_stream_putle32(&bs, 0); - - byte_stream_putle16(&bs, 0x0001); - byte_stream_putle32(&bs, 0); - byte_stream_putle16(&bs, strlen(args->rtfmsg)+1); - byte_stream_putraw(&bs, (const guint8 *)args->rtfmsg, strlen(args->rtfmsg)+1); - - byte_stream_putle32(&bs, args->fgcolor); - byte_stream_putle32(&bs, args->bgcolor); - byte_stream_putle32(&bs, strlen(rtfcap)+1); - byte_stream_putraw(&bs, (const guint8 *)rtfcap, strlen(rtfcap)+1); - - flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, 0x0000, snacid, &bs); - - byte_stream_destroy(&bs); - - return 0; -} - /** * Cancel a rendezvous invitation. It could be an invitation to * establish a direct connection, or a file-send, or a chat invite. @@ -1047,17 +797,6 @@ aim_tlvlist_add_noval(&inner_tlvlist, 0x000f); /* TODO: Send 0x0016 and 0x0017 */ -#if 0 - /* TODO: If the following is ever enabled, ensure that it is - * not sent with a receive redirect or stage 3 proxy - * redirect for a file receive (same conditions for - * sending 0x000f above) - */ - aim_tlvlist_add_raw(&inner_tlvlist, 0x000e, 2, "en"); - aim_tlvlist_add_raw(&inner_tlvlist, 0x000d, 8, "us-ascii"); - aim_tlvlist_add_raw(&inner_tlvlist, 0x000c, 24, "Please accept this file."); -#endif - if (filename != NULL) { ByteStream inner_bs; @@ -1139,17 +878,6 @@ aim_tlvlist_add_raw(&inner_tlvlist, 0x0016, 4, ip_comp); aim_tlvlist_add_16(&inner_tlvlist, 0x0017, ~pin); -#if 0 - /* TODO: If the following is ever enabled, ensure that it is - * not sent with a receive redirect or stage 3 proxy - * redirect for a file receive (same conditions for - * sending 0x000f above) - */ - aim_tlvlist_add_raw(&inner_tlvlist, 0x000e, 2, "en"); - aim_tlvlist_add_raw(&inner_tlvlist, 0x000d, 8, "us-ascii"); - aim_tlvlist_add_raw(&inner_tlvlist, 0x000c, 24, "Please accept this file."); -#endif - if (filename != NULL) { ByteStream filename_bs; @@ -1184,525 +912,52 @@ byte_stream_destroy(&bs); } -/** - * Subtype 0x0006 - Request the status message of the given ICQ user. - * - * @param od The oscar session. - * @param bn The UIN of the user of whom you wish to request info. - * @param type The type of info you wish to request. This should be the current - * state of the user, as one of the AIM_ICQ_STATE_* defines. - * @return Return 0 if no errors, otherwise return the error number. - */ -int aim_im_sendch2_geticqaway(OscarData *od, const char *bn, int type) -{ - FlapConnection *conn; - ByteStream bs; - aim_snacid_t snacid; - guchar cookie[8]; - - if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)) || !bn) - return -EINVAL; - - aim_icbm_makecookie(cookie); - - byte_stream_new(&bs, 8+2+1+strlen(bn) + 4+0x5e + 4); - - snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0); - - /* ICBM header */ - aim_im_puticbm(&bs, cookie, 0x0002, bn); - - /* TLV t(0005) - Encompasses almost everything below. */ - byte_stream_put16(&bs, 0x0005); /* T */ - byte_stream_put16(&bs, 0x005e); /* L */ - { /* V */ - byte_stream_put16(&bs, 0x0000); - - /* Cookie */ - byte_stream_putraw(&bs, cookie, 8); - - /* Put the 16 byte server relay capability */ - byte_stream_putcaps(&bs, OSCAR_CAPABILITY_ICQSERVERRELAY); - - /* TLV t(000a) */ - byte_stream_put16(&bs, 0x000a); - byte_stream_put16(&bs, 0x0002); - byte_stream_put16(&bs, 0x0001); - - /* TLV t(000f) */ - byte_stream_put16(&bs, 0x000f); - byte_stream_put16(&bs, 0x0000); - - /* TLV t(2711) */ - byte_stream_put16(&bs, 0x2711); - byte_stream_put16(&bs, 0x0036); - { /* V */ - byte_stream_putle16(&bs, 0x001b); /* L */ - byte_stream_putle16(&bs, 0x0009); /* Protocol version */ - byte_stream_putcaps(&bs, OSCAR_CAPABILITY_EMPTY); - byte_stream_putle16(&bs, 0x0000); /* Unknown */ - byte_stream_putle16(&bs, 0x0001); /* Client features? */ - byte_stream_putle16(&bs, 0x0000); /* Unknown */ - byte_stream_putle8(&bs, 0x00); /* Unkizown */ - byte_stream_putle16(&bs, 0xffff); /* Sequence number? XXX - This should decrement by 1 with each request */ - - byte_stream_putle16(&bs, 0x000e); /* L */ - byte_stream_putle16(&bs, 0xffff); /* Sequence number? XXX - This should decrement by 1 with each request */ - byte_stream_putle32(&bs, 0x00000000); /* Unknown */ - byte_stream_putle32(&bs, 0x00000000); /* Unknown */ - byte_stream_putle32(&bs, 0x00000000); /* Unknown */ - - /* The type of status message being requested */ - if (type & AIM_ICQ_STATE_CHAT) - byte_stream_putle16(&bs, 0x03ec); - else if(type & AIM_ICQ_STATE_DND) - byte_stream_putle16(&bs, 0x03eb); - else if(type & AIM_ICQ_STATE_OUT) - byte_stream_putle16(&bs, 0x03ea); - else if(type & AIM_ICQ_STATE_BUSY) - byte_stream_putle16(&bs, 0x03e9); - else if(type & AIM_ICQ_STATE_AWAY) - byte_stream_putle16(&bs, 0x03e8); - - byte_stream_putle16(&bs, 0x0001); /* Status? */ - byte_stream_putle16(&bs, 0x0001); /* Priority of this message? */ - byte_stream_putle16(&bs, 0x0001); /* L */ - byte_stream_putle8(&bs, 0x00); /* String of length L */ - } /* End TLV t(2711) */ - } /* End TLV t(0005) */ - - /* TLV t(0003) */ - byte_stream_put16(&bs, 0x0003); - byte_stream_put16(&bs, 0x0000); - - flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, 0x0000, snacid, &bs); - - byte_stream_destroy(&bs); - - return 0; -} - -/** - * Subtype 0x0006 - Send an ICQ-esque ICBM. - * - * This can be used to send an ICQ authorization reply (deny or grant). It is the "old way." - * The new way is to use SSI. I like the new way a lot better. This seems like such a hack, - * mostly because it's in network byte order. Figuring this stuff out sometimes takes a while, - * but thats ok, because it gives me time to try to figure out what kind of drugs the AOL people - * were taking when they merged the two protocols. - * - * @param bn The destination buddy name. - * @param type The type of message. 0x0007 for authorization denied. 0x0008 for authorization granted. - * @param message The message you want to send, it should be null terminated. - * @return Return 0 if no errors, otherwise return the error number. - */ -int aim_im_sendch4(OscarData *od, const char *bn, guint16 type, const char *message) +static void +incomingim_ch1_parsemsg(OscarData *od, aim_userinfo_t *userinfo, ByteStream *message, struct aim_incomingim_ch1_args *args) { - FlapConnection *conn; - ByteStream bs; - aim_snacid_t snacid; - guchar cookie[8]; - - if (!od || !(conn = flap_connection_findbygroup(od, 0x0002))) - return -EINVAL; - - if (!bn || !type || !message) - return -EINVAL; - - byte_stream_new(&bs, 8+3+strlen(bn)+12+strlen(message)+1+4); - - snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0); - - aim_icbm_makecookie(cookie); - - /* ICBM header */ - aim_im_puticbm(&bs, cookie, 0x0004, bn); - + PurpleAccount *account = purple_connection_get_account(od->gc); /* - * TLV t(0005) - * - * ICQ data (the UIN and the message). + * We're interested in the inner TLV 0x101, which contains precious, precious message. */ - byte_stream_put16(&bs, 0x0005); - byte_stream_put16(&bs, 4 + 2+2+strlen(message)+1); - - /* - * Your UIN - */ - byte_stream_putuid(&bs, od); - - /* - * TLV t(type) l(strlen(message)+1) v(message+NULL) - */ - byte_stream_putle16(&bs, type); - byte_stream_putle16(&bs, strlen(message)+1); - byte_stream_putraw(&bs, (const guint8 *)message, strlen(message)+1); - - /* - * TLV t(0006) l(0000) v() - */ - byte_stream_put16(&bs, 0x0006); - byte_stream_put16(&bs, 0x0000); - - flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, 0x0000, snacid, &bs); - - byte_stream_destroy(&bs); - - return 0; -} + while (byte_stream_bytes_left(message) >= 4) { + guint16 type = byte_stream_get16(message); + guint16 length = byte_stream_get16(message); + if (type == 0x101) { + gchar *msg; + guint16 msglen = length - 4; /* charset + charsubset */ + guint16 charset = byte_stream_get16(message); + byte_stream_advance(message, 2); /* charsubset */ -/* - * XXX - I don't see when this would ever get called... - */ -static int outgoingim(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) -{ - int ret = 0; - aim_rxcallback_t userfunc; - guchar cookie[8]; - guint16 channel; - GSList *tlvlist; - char *bn; - int bnlen; - guint16 icbmflags = 0; - guint8 flag1 = 0, flag2 = 0; - gchar *msg = NULL; - aim_tlv_t *msgblock; - - /* ICBM Cookie. */ - aim_icbm_makecookie(cookie); - - /* Channel ID */ - channel = byte_stream_get16(bs); - - if (channel != 0x01) { - purple_debug_misc("oscar", "icbm: ICBM received on unsupported channel. Ignoring. (chan = %04x)\n", channel); - return 0; + msg = byte_stream_getstr(message, msglen); + args->msg = oscar_decode_im(account, userinfo->bn, charset, msg, msglen); + } else { + byte_stream_advance(message, length); + } } - - bnlen = byte_stream_get8(bs); - bn = byte_stream_getstr(bs, bnlen); - - tlvlist = aim_tlvlist_read(bs); - - if (aim_tlv_gettlv(tlvlist, 0x0003, 1)) - icbmflags |= AIM_IMFLAGS_ACK; - if (aim_tlv_gettlv(tlvlist, 0x0004, 1)) - icbmflags |= AIM_IMFLAGS_AWAY; - - if ((msgblock = aim_tlv_gettlv(tlvlist, 0x0002, 1))) { - ByteStream mbs; - int featurelen, msglen; - - byte_stream_init(&mbs, msgblock->value, msgblock->length); - - byte_stream_get8(&mbs); - byte_stream_get8(&mbs); - for (featurelen = byte_stream_get16(&mbs); featurelen; featurelen--) - byte_stream_get8(&mbs); - byte_stream_get8(&mbs); - byte_stream_get8(&mbs); - - msglen = byte_stream_get16(&mbs) - 4; /* final block length */ - - flag1 = byte_stream_get16(&mbs); - flag2 = byte_stream_get16(&mbs); - - msg = byte_stream_getstr(&mbs, msglen); - } - - if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) - ret = userfunc(od, conn, frame, channel, bn, msg, icbmflags, flag1, flag2); - - g_free(bn); - g_free(msg); - aim_tlvlist_free(tlvlist); - - return ret; } -/* - * Ahh, the joys of nearly ridiculous over-engineering. - * - * Not only do AIM ICBM's support multiple channels. Not only do they - * support multiple character sets. But they support multiple character - * sets / encodings within the same ICBM. - * - * These multipart messages allow for complex space savings techniques, which - * seem utterly unnecessary by today's standards. In fact, there is only - * one client still in popular use that still uses this method: AOL for the - * Macintosh, Version 5.0. Obscure, yes, I know. - * - * In modern (non-"legacy") clients, if the user tries to send a character - * that is not ISO-8859-1 or ASCII, the client will send the entire message - * as UNICODE, meaning that every character in the message will occupy the - * full 16 bit UNICODE field, even if the high order byte would be zero. - * Multipart messages prevent this wasted space by allowing the client to - * only send the characters in UNICODE that need to be sent that way, and - * the rest of the message can be sent in whatever the native character - * set is (probably ASCII). - * - * An important note is that sections will be displayed in the order that - * they appear in the ICBM. There is no facility for merging or rearranging - * sections at run time. So if you have, say, ASCII then UNICODE then ASCII, - * you must supply two ASCII sections with a UNICODE in the middle, and incur - * the associated overhead. - * - * Normally I would have laughed and given a firm 'no' to supporting this - * seldom-used feature, but something is attracting me to it. In the future, - * it may be possible to abuse this to send mixed-media messages to other - * open source clients (like encryption or something) -- see faimtest for - * examples of how to do this. - * - * I would definitely recommend avoiding this feature unless you really - * know what you are doing, and/or you have something neat to do with it. - * - */ -int aim_mpmsg_init(OscarData *od, aim_mpmsg_t *mpm) -{ - - memset(mpm, 0, sizeof(aim_mpmsg_t)); - - return 0; -} - -static int mpmsg_addsection(OscarData *od, aim_mpmsg_t *mpm, guint16 charset, guint16 charsubset, gchar *data, guint16 datalen) -{ - aim_mpmsg_section_t *sec; - - sec = g_malloc(sizeof(aim_mpmsg_section_t)); - - sec->charset = charset; - sec->charsubset = charsubset; - sec->data = data; - sec->datalen = datalen; - sec->next = NULL; - - if (!mpm->parts) - mpm->parts = sec; - else { - aim_mpmsg_section_t *cur; - - for (cur = mpm->parts; cur->next; cur = cur->next) - ; - cur->next = sec; - } - - mpm->numparts++; - - return 0; -} - -int aim_mpmsg_addraw(OscarData *od, aim_mpmsg_t *mpm, guint16 charset, guint16 charsubset, const gchar *data, guint16 datalen) -{ - gchar *dup; - - dup = g_malloc(datalen); - memcpy(dup, data, datalen); - - if (mpmsg_addsection(od, mpm, charset, charsubset, dup, datalen) == -1) { - g_free(dup); - return -1; - } - - return 0; -} - -/* XXX - should provide a way of saying ISO-8859-1 specifically */ -int aim_mpmsg_addascii(OscarData *od, aim_mpmsg_t *mpm, const char *ascii) -{ - gchar *dup; - - if (!(dup = g_strdup(ascii))) - return -1; - - if (mpmsg_addsection(od, mpm, 0x0000, 0x0000, dup, strlen(ascii)) == -1) { - g_free(dup); - return -1; - } - - return 0; -} - -int aim_mpmsg_addunicode(OscarData *od, aim_mpmsg_t *mpm, const guint16 *unicode, guint16 unicodelen) -{ - gchar *buf; - ByteStream bs; - int i; - - buf = g_malloc(unicodelen * 2); - - byte_stream_init(&bs, (guchar *)buf, unicodelen * 2); - - /* We assume unicode is in /host/ byte order -- convert to network */ - for (i = 0; i < unicodelen; i++) - byte_stream_put16(&bs, unicode[i]); - - if (mpmsg_addsection(od, mpm, 0x0002, 0x0000, buf, byte_stream_curpos(&bs)) == -1) { - g_free(buf); - return -1; - } - - return 0; -} - -void aim_mpmsg_free(OscarData *od, aim_mpmsg_t *mpm) +static int +incomingim_ch1(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, ByteStream *bs, guint8 *cookie) { - aim_mpmsg_section_t *cur; - - for (cur = mpm->parts; cur; ) { - aim_mpmsg_section_t *tmp; - - tmp = cur->next; - g_free(cur->data); - g_free(cur); - cur = tmp; - } - - mpm->numparts = 0; - mpm->parts = NULL; - - return; -} - -/* - * Start by building the multipart structures, then pick the first - * human-readable section and stuff it into args->msg so no one gets - * suspicious. - */ -static int incomingim_ch1_parsemsgs(OscarData *od, aim_userinfo_t *userinfo, guint8 *data, int len, struct aim_incomingim_ch1_args *args) -{ - /* Should this be ASCII -> UNICODE -> Custom */ - static const guint16 charsetpri[] = { - AIM_CHARSET_ASCII, /* ASCII first */ - AIM_CHARSET_LATIN_1, /* then ISO-8859-1 */ - AIM_CHARSET_UNICODE, /* UNICODE as last resort */ - }; - static const int charsetpricount = 3; - int i; - ByteStream mbs; - aim_mpmsg_section_t *sec; - - byte_stream_init(&mbs, data, len); - - while (byte_stream_empty(&mbs)) { - guint16 msglen, flag1, flag2; - gchar *msgbuf; - - byte_stream_get8(&mbs); /* 01 */ - byte_stream_get8(&mbs); /* 01 */ - - /* Message string length, including character set info. */ - msglen = byte_stream_get16(&mbs); - if (msglen > byte_stream_empty(&mbs)) - { - purple_debug_misc("oscar", "Received an IM containing an invalid message part from %s. They are probably trying to do something malicious.\n", userinfo->bn); - break; - } - - /* Character set info */ - flag1 = byte_stream_get16(&mbs); - flag2 = byte_stream_get16(&mbs); - - /* Message. */ - msglen -= 4; - - /* - * For now, we don't care what the encoding is. Just copy - * it into a multipart struct and deal with it later. However, - * always pad the ending with a NULL. This makes it easier - * to treat ASCII sections as strings. It won't matter for - * UNICODE or binary data, as you should never read past - * the specified data length, which will not include the pad. - * - * XXX - There's an API bug here. For sending, the UNICODE is - * given in host byte order (aim_mpmsg_addunicode), but here - * the received messages are given in network byte order. - * - */ - msgbuf = (gchar *)byte_stream_getraw(&mbs, msglen); - mpmsg_addsection(od, &args->mpmsg, flag1, flag2, msgbuf, msglen); - - } /* while */ - - args->icbmflags |= AIM_IMFLAGS_MULTIPART; /* always set */ - - /* - * Clients that support multiparts should never use args->msg, as it - * will point to an arbitrary section. - * - * Here, we attempt to provide clients that do not support multipart - * messages with something to look at -- hopefully a human-readable - * string. But, failing that, a UNICODE message, or nothing at all. - * - * Which means that even if args->msg is NULL, it does not mean the - * message was blank. - * - */ - for (i = 0; i < charsetpricount; i++) { - for (sec = args->mpmsg.parts; sec; sec = sec->next) { - - if (sec->charset != charsetpri[i]) - continue; - - /* Great. We found one. Fill it in. */ - args->charset = sec->charset; - args->charsubset = sec->charsubset; - - /* Set up the simple flags */ - switch (args->charsubset) - { - case 0x0000: - /* standard subencoding? */ - break; - case 0x000b: - args->icbmflags |= AIM_IMFLAGS_SUBENC_MACINTOSH; - break; - case 0xffff: - /* no subencoding */ - break; - default: - break; - } - - args->msg = sec->data; - args->msglen = sec->datalen; - - return 0; - } - } - - /* No human-readable sections found. Oh well. */ - args->charset = args->charsubset = 0xffff; - args->msg = NULL; - args->msglen = 0; - - return 0; -} - -static int incomingim_ch1(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, ByteStream *bs, guint8 *cookie) -{ - guint16 type, length, magic1, msglen = 0; + guint16 type, length; aim_rxcallback_t userfunc; int ret = 0; - int rev = 0; struct aim_incomingim_ch1_args args; unsigned int endpos; memset(&args, 0, sizeof(args)); - aim_mpmsg_init(od, &args.mpmsg); - /* * This used to be done using tlvchains. For performance reasons, * I've changed it to process the TLVs in-place. This avoids lots * of per-IM memory allocations. */ - while (byte_stream_empty(bs) >= 4) + while (byte_stream_bytes_left(bs) >= 4) { type = byte_stream_get16(bs); length = byte_stream_get16(bs); - if (length > byte_stream_empty(bs)) + if (length > byte_stream_bytes_left(bs)) { purple_debug_misc("oscar", "Received an IM containing an invalid message part from %s. They are probably trying to do something malicious.\n", userinfo->bn); break; @@ -1711,93 +966,20 @@ endpos = byte_stream_curpos(bs) + length; if (type == 0x0002) { /* Message Block */ - - /* - * This TLV consists of the following: - * - 0501 -- Unknown - * - Features: Don't know how to interpret these - * - 0101 -- Unknown - * - Message - * - * Slick and possible others reverse 'Features' and 'Messages' section. - * Thus, the TLV could have following layout: - * - 0101 -- Unknown (possibly magic for message section) - * - Message - * - 0501 -- Unknown (possibly magic for features section) - * - Features: Don't know how to interpret these - */ - - magic1 = byte_stream_get16(bs); /* 0501 or 0101 */ - if (magic1 == 0x101) /* Bad, message comes before attributes */ - { - /* Jump to the features section */ - msglen = byte_stream_get16(bs); - bs->offset += msglen; - rev = 1; - - magic1 = byte_stream_get16(bs); /* 0501 */ - } - - if (magic1 != 0x501) - { - purple_debug_misc("oscar", "Received an IM containing an invalid message part from %s. They are probably trying to do something malicious.\n", userinfo->bn); - break; - } - - args.featureslen = byte_stream_get16(bs); - if (args.featureslen > byte_stream_empty(bs)) - { - purple_debug_misc("oscar", "Received an IM containing an invalid message part from %s. They are probably trying to do something malicious.\n", userinfo->bn); - break; - } - if (args.featureslen == 0) - { - args.features = NULL; - } - else - { - args.features = byte_stream_getraw(bs, args.featureslen); - args.icbmflags |= AIM_IMFLAGS_CUSTOMFEATURES; - } - - if (rev) - { - /* Fix buffer back to message */ - bs->offset -= args.featureslen + 2 + 2 + msglen + 2 + 2; - } - - magic1 = byte_stream_get16(bs); /* 01 01 */ - if (magic1 != 0x101) /* Bad, message comes before attributes */ - { - purple_debug_misc("oscar", "Received an IM containing an invalid message part from %s. They are probably trying to do something malicious.\n", userinfo->bn); - break; - } - msglen = byte_stream_get16(bs); - - /* - * The rest of the TLV contains one or more message - * blocks... - */ - incomingim_ch1_parsemsgs(od, userinfo, bs->data + bs->offset - 2 - 2 /* XXX evil!!! */, msglen + 2 + 2, &args); - + ByteStream tlv02; + byte_stream_init(&tlv02, bs->data + bs->offset, length); + incomingim_ch1_parsemsg(od, userinfo, &tlv02, &args); } else if (type == 0x0003) { /* Server Ack Requested */ - args.icbmflags |= AIM_IMFLAGS_ACK; - } else if (type == 0x0004) { /* Message is Auto Response */ - args.icbmflags |= AIM_IMFLAGS_AWAY; - } else if (type == 0x0006) { /* Message was received offline. */ - /* * This flag is set on incoming offline messages for both * AIM and ICQ accounts. */ args.icbmflags |= AIM_IMFLAGS_OFFLINE; - } else if (type == 0x0008) { /* I-HAVE-A-REALLY-PURTY-ICON Flag */ - args.iconlen = byte_stream_get32(bs); byte_stream_get16(bs); /* 0x0001 */ args.iconsum = byte_stream_get16(bs); @@ -1815,39 +997,16 @@ */ if (args.iconlen) args.icbmflags |= AIM_IMFLAGS_HASICON; - } else if (type == 0x0009) { - args.icbmflags |= AIM_IMFLAGS_BUDDYREQ; - } else if (type == 0x000b) { /* Non-direct connect typing notification */ - args.icbmflags |= AIM_IMFLAGS_TYPINGNOT; - } else if (type == 0x0016) { - /* * UTC timestamp for when the message was sent. Only * provided for offline messages. */ args.timestamp = byte_stream_get32(bs); - - } else if (type == 0x0017) { - - if (length > byte_stream_empty(bs)) - { - purple_debug_misc("oscar", "Received an IM containing an invalid message part from %s. They are probably trying to do something malicious.\n", userinfo->bn); - break; - } - g_free(args.extdata); - args.extdatalen = length; - if (args.extdatalen == 0) - args.extdata = NULL; - else - args.extdata = byte_stream_getraw(bs, args.extdatalen); - - } else { - purple_debug_misc("oscar", "incomingim_ch1: unknown TLV 0x%04x (len %d)\n", type, length); } /* @@ -1865,10 +1024,7 @@ if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) ret = userfunc(od, conn, frame, channel, userinfo, &args); - aim_mpmsg_free(od, &args.mpmsg); - g_free(args.features); - g_free(args.extdata); - + g_free(args.msg); return ret; } @@ -1894,7 +1050,7 @@ * ... * ... */ - while (byte_stream_empty(servdata)) + while (byte_stream_bytes_left(servdata)) { guint16 gnlen, numb; int i; @@ -1966,7 +1122,7 @@ static void incomingim_ch2_icqserverrelay_free(OscarData *od, IcbmArgsCh2 *args) { - g_free((char *)args->info.rtfmsg.rtfmsg); + g_free((char *)args->info.rtfmsg.msg); } /* @@ -1980,33 +1136,34 @@ static void incomingim_ch2_icqserverrelay(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, aim_userinfo_t *userinfo, IcbmArgsCh2 *args, ByteStream *servdata) { - guint16 hdrlen, anslen, msglen; + guint16 hdrlen, msglen; + + args->destructor = (void *)incomingim_ch2_icqserverrelay_free; - if (byte_stream_empty(servdata) < 24) - /* Someone sent us a short server relay ICBM. Weird. (Maybe?) */ - return; - - hdrlen = byte_stream_getle16(servdata); - byte_stream_advance(servdata, hdrlen); - - hdrlen = byte_stream_getle16(servdata); +#define SKIP_HEADER(expected_hdrlen) \ + hdrlen = byte_stream_getle16(servdata); \ + if (hdrlen != expected_hdrlen) { \ + purple_debug_warning("oscar", "Expected to find a header with length " #expected_hdrlen "; ignoring message"); \ + return; \ + } \ byte_stream_advance(servdata, hdrlen); - args->info.rtfmsg.msgtype = byte_stream_getle16(servdata); + SKIP_HEADER(0x001b); + SKIP_HEADER(0x000e); - anslen = byte_stream_getle32(servdata); - byte_stream_advance(servdata, anslen); + args->info.rtfmsg.msgtype = byte_stream_get8(servdata); + /* + * Copied from http://iserverd.khstu.ru/oscar/message.html: + * xx byte message flags + * xx xx word (LE) status code + * xx xx word (LE) priority code + * + * We don't need any of these, so just skip them. + */ + byte_stream_advance(servdata, 1 + 2 + 2); msglen = byte_stream_getle16(servdata); - args->info.rtfmsg.rtfmsg = byte_stream_getstr(servdata, msglen); - - args->info.rtfmsg.fgcolor = byte_stream_getle32(servdata); - args->info.rtfmsg.bgcolor = byte_stream_getle32(servdata); - - hdrlen = byte_stream_getle32(servdata); - byte_stream_advance(servdata, hdrlen); - - args->destructor = (void *)incomingim_ch2_icqserverrelay_free; + args->info.rtfmsg.msg = byte_stream_getstr(servdata, msglen); } static void @@ -2191,20 +1348,6 @@ if (aim_tlv_gettlv(list2, 0x000e, 1)) args.language = aim_tlv_getstr(list2, 0x000e, 1); -#if 0 - /* - * Unknown -- no value - * - * Maybe means we should connect directly to transfer the file? - * Also used in ICQ Lite Beta 4.0 URLs. Also empty. - */ - /* I don't think this indicates a direct transfer; this flag is - * also present in a stage 1 proxied file send request -- Jonathan */ - if (aim_tlv_gettlv(list2, 0x000f, 1)) { - /* Unhandled */ - } -#endif - /* * Flag meaning we should proxy the file transfer through an AIM server */ @@ -2399,38 +1542,6 @@ return ret; } -/* - * Subtype 0x0008 - Send a warning to bn. - * - * Flags: - * AIM_WARN_ANON Send as an anonymous (doesn't count as much) - * - * returns -1 on error (couldn't alloc packet), 0 on success. - * - */ -int aim_im_warn(OscarData *od, FlapConnection *conn, const char *bn, guint32 flags) -{ - ByteStream bs; - aim_snacid_t snacid; - - if (!od || !conn || !bn) - return -EINVAL; - - byte_stream_new(&bs, strlen(bn)+3); - - snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0008, 0x0000, bn, strlen(bn)+1); - - byte_stream_put16(&bs, (flags & AIM_WARN_ANON) ? 0x0001 : 0x0000); - byte_stream_put8(&bs, strlen(bn)); - byte_stream_putstr(&bs, bn); - - flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0008, 0x0000, snacid, &bs); - - byte_stream_destroy(&bs); - - return 0; -} - /* Subtype 0x000a */ static int missedcall(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { @@ -2439,7 +1550,7 @@ guint16 channel, nummissed, reason; aim_userinfo_t userinfo; - while (byte_stream_empty(bs)) { + while (byte_stream_bytes_left(bs)) { channel = byte_stream_get16(bs); aim_info_extract(od, bs, &userinfo); @@ -2459,9 +1570,7 @@ * Subtype 0x000b * * Possible codes: - * AIM_TRANSFER_DENY_NOTSUPPORTED -- "client does not support" * AIM_TRANSFER_DENY_DECLINE -- "client has declined transfer" - * AIM_TRANSFER_DENY_NOTACCEPTING -- "client is not accepting transfers" * */ int aim_im_denytransfer(OscarData *od, const char *bn, const guchar *cookie, guint16 code) @@ -2638,16 +1747,10 @@ } /* - * Subtype 0x000c - Receive an ack after sending an ICBM. - * - * You have to have send the message with the AIM_IMFLAGS_ACK flag set - * (TLV t(0003)). The ack contains the ICBM header of the message you - * sent. - * + * Subtype 0x000c - Receive an ack after sending an ICBM. The ack contains the ICBM header of the message you sent. */ static int msgack(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) { - aim_rxcallback_t userfunc; guint16 ch; guchar *cookie; char *bn; @@ -2657,8 +1760,7 @@ ch = byte_stream_get16(bs); bn = byte_stream_getstr(bs, byte_stream_get8(bs)); - if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) - ret = userfunc(od, conn, frame, ch, bn); + purple_debug_info("oscar", "Sent message to %s.\n", bn); g_free(bn); g_free(cookie); @@ -2951,8 +2053,6 @@ return error(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0005) return aim_im_paraminfo(od, conn, mod, frame, snac, bs); - else if (snac->subtype == 0x0006) - return outgoingim(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x0007) return incomingim(od, conn, mod, frame, snac, bs); else if (snac->subtype == 0x000a)
--- a/libpurple/protocols/oscar/family_icq.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/family_icq.c Thu Jul 29 00:06:56 2010 +0000 @@ -23,6 +23,7 @@ * */ +#include "encoding.h" #include "oscar.h" #define AIM_ICQ_INFO_REQUEST 0x04b2
--- a/libpurple/protocols/oscar/family_invite.c Thu Jul 08 17:00:45 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/* - * Purple's oscar protocol plugin - * This file is the legal property of its developers. - * Please see the AUTHORS file distributed alongside this file. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA -*/ - -/* - * Family 0x0006 - This isn't really ever used by anyone anymore. - * - * Once upon a time, there used to be a menu item in AIM clients that - * said something like "Invite a friend to use AIM..." and then it would - * ask for an email address and it would sent a mail to them saying - * how perfectly wonderful the AIM service is and why you should use it - * and click here if you hate the person who sent this to you and want to - * complain and yell at them in a small box with pretty fonts. - * - * I could've sworn libfaim had this implemented once, a long long time ago, - * but I can't find it. - * - * I'm mainly adding this so that I can keep advertising that we support - * group 6, even though we don't. - * - */ - -#include "oscar.h" - -int invite_modfirst(OscarData *od, aim_module_t *mod) -{ - - mod->family = SNAC_FAMILY_INVITE; - mod->version = 0x0001; - mod->toolid = 0x0110; - mod->toolversion = 0x0629; - mod->flags = 0; - strncpy(mod->name, "invite", sizeof(mod->name)); - mod->snachandler = NULL; - - return 0; -}
--- a/libpurple/protocols/oscar/family_locate.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/family_locate.c Thu Jul 29 00:06:56 2010 +0000 @@ -583,7 +583,7 @@ guint64 flags = 0; int offset; - for (offset = 0; byte_stream_empty(bs) && (offset < len); offset += 0x10) { + for (offset = 0; byte_stream_bytes_left(bs) && (offset < len); offset += 0x10) { guint8 *cap; int i, identified; @@ -617,7 +617,7 @@ int offset; const char *result = NULL; - for (offset = 0; byte_stream_empty(bs) && (offset < len); offset += 0x10) { + for (offset = 0; byte_stream_bytes_left(bs) && (offset < len); offset += 0x10) { /* check wheather this capability is a custom user icon */ guint8 *cap; int i; @@ -643,7 +643,7 @@ guint64 flags = 0; int offset; - for (offset = 0; byte_stream_empty(bs) && (offset < len); offset += 0x02) { + for (offset = 0; byte_stream_bytes_left(bs) && (offset < len); offset += 0x02) { guint8 *cap; int i, identified; @@ -674,7 +674,7 @@ if (!bs) return -EINVAL; - for (i = 0; byte_stream_empty(bs); i++) { + for (i = 0; byte_stream_bytes_left(bs); i++) { if (aim_caps[i].flag == OSCAR_CAPABILITY_LAST) break; @@ -804,7 +804,7 @@ type = byte_stream_get16(bs); length = byte_stream_get16(bs); curpos = byte_stream_curpos(bs); - endpos = curpos + MIN(length, byte_stream_empty(bs)); + endpos = curpos + MIN(length, byte_stream_bytes_left(bs)); if (type == 0x0001) { /* @@ -1010,7 +1010,7 @@ number2 = byte_stream_get8(bs); length2 = byte_stream_get8(bs); - endpos2 = byte_stream_curpos(bs) + MIN(length2, byte_stream_empty(bs)); + endpos2 = byte_stream_curpos(bs) + MIN(length2, byte_stream_bytes_left(bs)); switch (type2) { case 0x0000: { /* This is an official buddy icon? */ @@ -1165,60 +1165,6 @@ return 0; } -/* Apparently, this is never called. - * If you activate it, figure out a way to know what mood to pass to - * aim_tlvlist_add_caps() below. --rlaager */ -#if 0 -/* - * Inverse of aim_info_extract() - */ -int -aim_putuserinfo(ByteStream *bs, aim_userinfo_t *info) -{ - GSList *tlvlist = NULL; - - if (!bs || !info) - return -EINVAL; - - byte_stream_put8(bs, strlen(info->bn)); - byte_stream_putstr(bs, info->bn); - - byte_stream_put16(bs, info->warnlevel); - - if (info->present & AIM_USERINFO_PRESENT_FLAGS) - aim_tlvlist_add_16(&tlvlist, 0x0001, info->flags); - if (info->present & AIM_USERINFO_PRESENT_MEMBERSINCE) - aim_tlvlist_add_32(&tlvlist, 0x0002, info->membersince); - if (info->present & AIM_USERINFO_PRESENT_ONLINESINCE) - aim_tlvlist_add_32(&tlvlist, 0x0003, info->onlinesince); - if (info->present & AIM_USERINFO_PRESENT_IDLE) - aim_tlvlist_add_16(&tlvlist, 0x0004, info->idletime); - -/* XXX - So, ICQ_OSCAR_SUPPORT is never defined anywhere... */ -#ifdef ICQ_OSCAR_SUPPORT - if (atoi(info->bn) != 0) { - if (info->present & AIM_USERINFO_PRESENT_ICQEXTSTATUS) - aim_tlvlist_add_16(&tlvlist, 0x0006, info->icqinfo.status); - if (info->present & AIM_USERINFO_PRESENT_ICQIPADDR) - aim_tlvlist_add_32(&tlvlist, 0x000a, info->icqinfo.ipaddr); - } -#endif - - if (info->present & AIM_USERINFO_PRESENT_CAPABILITIES) { - aim_tlvlist_add_caps(&tlvlist, 0x000d, info->capabilities, NULL); - } - - if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN) - aim_tlvlist_add_32(&tlvlist, (guint16)((info->flags & AIM_FLAG_AOL) ? 0x0010 : 0x000f), info->sessionlen); - - byte_stream_put16(bs, aim_tlvlist_count(tlvlist)); - aim_tlvlist_write(bs, &tlvlist); - aim_tlvlist_free(tlvlist); - - return 0; -} -#endif - /* * Subtype 0x0001 */ @@ -1427,40 +1373,6 @@ return 0; } -/* - * Subtype 0x0005 - Request info of another AIM user. - * - * @param bn The buddy name whose info you wish to request. - * @param infotype The type of info you wish to request. - * 0x0001 - Info/profile - * 0x0003 - Away message - * 0x0004 - Capabilities - */ -int -aim_locate_getinfo(OscarData *od, const char *bn, guint16 infotype) -{ - FlapConnection *conn; - ByteStream bs; - aim_snacid_t snacid; - - if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)) || !bn) - return -EINVAL; - - byte_stream_new(&bs, 2+1+strlen(bn)); - - snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x0005, 0x0000, NULL, 0); - - byte_stream_put16(&bs, infotype); - byte_stream_put8(&bs, strlen(bn)); - byte_stream_putstr(&bs, bn); - - flap_connection_send_snac(od, conn, SNAC_FAMILY_LOCATE, 0x0005, 0x0000, snacid, &bs); - - byte_stream_destroy(&bs); - - return 0; -} - /* Subtype 0x0006 */ static int userinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) @@ -1523,133 +1435,6 @@ } /* - * Subtype 0x0009 - Set directory profile data. - * - * This is not the same as aim_location_setprofile! - * privacy: 1 to allow searching, 0 to disallow. - * - */ -int aim_locate_setdirinfo(OscarData *od, const char *first, const char *middle, const char *last, const char *maiden, const char *nickname, const char *street, const char *city, const char *state, const char *zip, int country, guint16 privacy) -{ - FlapConnection *conn; - ByteStream bs; - aim_snacid_t snacid; - GSList *tlvlist = NULL; - - if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE))) - return -EINVAL; - - aim_tlvlist_add_16(&tlvlist, 0x000a, privacy); - - if (first) - aim_tlvlist_add_str(&tlvlist, 0x0001, first); - if (last) - aim_tlvlist_add_str(&tlvlist, 0x0002, last); - if (middle) - aim_tlvlist_add_str(&tlvlist, 0x0003, middle); - if (maiden) - aim_tlvlist_add_str(&tlvlist, 0x0004, maiden); - - if (state) - aim_tlvlist_add_str(&tlvlist, 0x0007, state); - if (city) - aim_tlvlist_add_str(&tlvlist, 0x0008, city); - - if (nickname) - aim_tlvlist_add_str(&tlvlist, 0x000c, nickname); - if (zip) - aim_tlvlist_add_str(&tlvlist, 0x000d, zip); - - if (street) - aim_tlvlist_add_str(&tlvlist, 0x0021, street); - - byte_stream_new(&bs, aim_tlvlist_size(tlvlist)); - - snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x0009, 0x0000, NULL, 0); - - aim_tlvlist_write(&bs, &tlvlist); - aim_tlvlist_free(tlvlist); - - flap_connection_send_snac(od, conn, SNAC_FAMILY_LOCATE, 0x0009, 0x0000, snacid, &bs); - - byte_stream_destroy(&bs); - - return 0; -} - -/* - * Subtype 0x000b - Huh? What is this? - */ -int aim_locate_000b(OscarData *od, const char *bn) -{ - FlapConnection *conn; - ByteStream bs; - aim_snacid_t snacid; - - return -EINVAL; - - if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)) || !bn) - return -EINVAL; - - byte_stream_new(&bs, 1+strlen(bn)); - - snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x000b, 0x0000, NULL, 0); - - byte_stream_put8(&bs, strlen(bn)); - byte_stream_putstr(&bs, bn); - - flap_connection_send_snac(od, conn, SNAC_FAMILY_LOCATE, 0x000b, 0x0000, snacid, &bs); - - byte_stream_destroy(&bs); - - return 0; -} - -/* - * Subtype 0x000f - * - * XXX pass these in better - * - */ -int -aim_locate_setinterests(OscarData *od, const char *interest1, const char *interest2, const char *interest3, const char *interest4, const char *interest5, guint16 privacy) -{ - FlapConnection *conn; - ByteStream bs; - aim_snacid_t snacid; - GSList *tlvlist = NULL; - - if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE))) - return -EINVAL; - - /* ?? privacy ?? */ - aim_tlvlist_add_16(&tlvlist, 0x000a, privacy); - - if (interest1) - aim_tlvlist_add_str(&tlvlist, 0x0000b, interest1); - if (interest2) - aim_tlvlist_add_str(&tlvlist, 0x0000b, interest2); - if (interest3) - aim_tlvlist_add_str(&tlvlist, 0x0000b, interest3); - if (interest4) - aim_tlvlist_add_str(&tlvlist, 0x0000b, interest4); - if (interest5) - aim_tlvlist_add_str(&tlvlist, 0x0000b, interest5); - - byte_stream_new(&bs, aim_tlvlist_size(tlvlist)); - - snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x000f, 0x0000, NULL, 0); - - aim_tlvlist_write(&bs, &tlvlist); - aim_tlvlist_free(tlvlist); - - flap_connection_send_snac(od, conn, SNAC_FAMILY_LOCATE, 0x000f, 0x0000, snacid, &bs); - - byte_stream_destroy(&bs); - return 0; -} - -/* * Subtype 0x0015 - Request the info of a user using the short method. This is * what iChat uses. It normally is VERY leniently rate limited. * @@ -1725,15 +1510,6 @@ return 0; } -#if 0 //rlaager -const char* aim_get_custom_icon_mood(gint32 no) -{ - if (no >= G_N_ELEMENTS(aim_custom_icons) || no < 1) - return NULL; - return aim_custom_icons[no].mood.mood; -} -#endif - const char* icq_get_custom_icon_description(const char *mood) {
--- a/libpurple/protocols/oscar/family_odir.c Thu Jul 08 17:00:45 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,264 +0,0 @@ -/* - * Purple's oscar protocol plugin - * This file is the legal property of its developers. - * Please see the AUTHORS file distributed alongside this file. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA -*/ - -/* - * Family 0x000f - Newer Search Method - * - * Used for searching for other AIM users by email address, name, - * location, commmon interests, and a few other similar things. - * - */ - -#include "oscar.h" - -/** - * Subtype 0x0002 - Submit a User Search Request - * - * Search for an AIM buddy based on their email address. - * - * @param od The oscar session. - * @param region Should be "us-ascii" unless you know what you're doing. - * @param email The email address you want to search for. - * @return Return 0 if no errors, otherwise return the error number. - */ -int aim_odir_email(OscarData *od, const char *region, const char *email) -{ - FlapConnection *conn; - ByteStream bs; - aim_snacid_t snacid; - GSList *tlvlist = NULL; - - if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ODIR)) || !region || !email) - return -EINVAL; - - /* Create a TLV chain, write it to the outgoing frame, then free the chain */ - aim_tlvlist_add_str(&tlvlist, 0x001c, region); - aim_tlvlist_add_16(&tlvlist, 0x000a, 0x0001); /* Type of search */ - aim_tlvlist_add_str(&tlvlist, 0x0005, email); - - byte_stream_new(&bs, aim_tlvlist_size(tlvlist)); - - aim_tlvlist_write(&bs, &tlvlist); - aim_tlvlist_free(tlvlist); - - snacid = aim_cachesnac(od, SNAC_FAMILY_ODIR, 0x0002, 0x0000, NULL, 0); - flap_connection_send_snac(od, conn, SNAC_FAMILY_ODIR, 0x0002, 0x0000, snacid, &bs); - - byte_stream_destroy(&bs); - - return 0; -} - - -/** - * Subtype 0x0002 - Submit a User Search Request - * - * Search for an AIM buddy based on various info - * about the person. - * - * @param od The oscar session. - * @param region Should be "us-ascii" unless you know what you're doing. - * @param first The first name of the person you want to search for. - * @param middle The middle name of the person you want to search for. - * @param last The last name of the person you want to search for. - * @param maiden The maiden name of the person you want to search for. - * @param nick The nick name of the person you want to search for. - * @param city The city where the person you want to search for resides. - * @param state The state where the person you want to search for resides. - * @param country The country where the person you want to search for resides. - * @param zip The zip code where the person you want to search for resides. - * @param address The street address where the person you want to seach for resides. - * @return Return 0 if no errors, otherwise return the error number. - */ -int aim_odir_name(OscarData *od, const char *region, const char *first, const char *middle, const char *last, const char *maiden, const char *nick, const char *city, const char *state, const char *country, const char *zip, const char *address) -{ - FlapConnection *conn; - ByteStream bs; - aim_snacid_t snacid; - GSList *tlvlist = NULL; - - if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ODIR)) || !region) - return -EINVAL; - - /* Create a TLV chain, write it to the outgoing frame, then free the chain */ - aim_tlvlist_add_str(&tlvlist, 0x001c, region); - aim_tlvlist_add_16(&tlvlist, 0x000a, 0x0000); /* Type of search */ - if (first) - aim_tlvlist_add_str(&tlvlist, 0x0001, first); - if (last) - aim_tlvlist_add_str(&tlvlist, 0x0002, last); - if (middle) - aim_tlvlist_add_str(&tlvlist, 0x0003, middle); - if (maiden) - aim_tlvlist_add_str(&tlvlist, 0x0004, maiden); - if (country) - aim_tlvlist_add_str(&tlvlist, 0x0006, country); - if (state) - aim_tlvlist_add_str(&tlvlist, 0x0007, state); - if (city) - aim_tlvlist_add_str(&tlvlist, 0x0008, city); - if (nick) - aim_tlvlist_add_str(&tlvlist, 0x000c, nick); - if (zip) - aim_tlvlist_add_str(&tlvlist, 0x000d, zip); - if (address) - aim_tlvlist_add_str(&tlvlist, 0x0021, address); - - byte_stream_new(&bs, aim_tlvlist_size(tlvlist)); - - aim_tlvlist_write(&bs, &tlvlist); - aim_tlvlist_free(tlvlist); - - snacid = aim_cachesnac(od, SNAC_FAMILY_ODIR, 0x0002, 0x0000, NULL, 0); - flap_connection_send_snac(od, conn, SNAC_FAMILY_ODIR, 0x0002, 0x0000, snacid, &bs); - - byte_stream_destroy(&bs); - - return 0; -} - - -/** - * Subtype 0x0002 - Submit a User Search Request - * - * @param od The oscar session. - * @param interest1 An interest you want to search for. - * @return Return 0 if no errors, otherwise return the error number. - */ -int aim_odir_interest(OscarData *od, const char *region, const char *interest) -{ - FlapConnection *conn; - ByteStream bs; - aim_snacid_t snacid; - GSList *tlvlist = NULL; - - if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ODIR)) || !region) - return -EINVAL; - - /* Create a TLV chain, write it to the outgoing frame, then free the chain */ - aim_tlvlist_add_str(&tlvlist, 0x001c, region); - aim_tlvlist_add_16(&tlvlist, 0x000a, 0x0001); /* Type of search */ - if (interest) - aim_tlvlist_add_str(&tlvlist, 0x0001, interest); - - byte_stream_new(&bs, aim_tlvlist_size(tlvlist)); - - aim_tlvlist_write(&bs, &tlvlist); - aim_tlvlist_free(tlvlist); - - snacid = aim_cachesnac(od, SNAC_FAMILY_ODIR, 0x0002, 0x0000, NULL, 0); - flap_connection_send_snac(od, conn, SNAC_FAMILY_ODIR, 0x0002, 0x0000, snacid, &bs); - - byte_stream_destroy(&bs); - - return 0; -} - - -/** - * Subtype 0x0003 - Receive Reply From a User Search - * - */ -static int parseresults(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) -{ - int ret = 0; - aim_rxcallback_t userfunc; - guint16 tmp, numresults; - struct aim_odir *results = NULL; - - tmp = byte_stream_get16(bs); /* Unknown */ - tmp = byte_stream_get16(bs); /* Unknown */ - byte_stream_advance(bs, tmp); - - numresults = byte_stream_get16(bs); /* Number of results to follow */ - - /* Allocate a linked list, 1 node per result */ - while (numresults) { - struct aim_odir *new; - GSList *tlvlist = aim_tlvlist_readnum(bs, byte_stream_get16(bs)); - new = (struct aim_odir *)g_malloc(sizeof(struct aim_odir)); - new->first = aim_tlv_getstr(tlvlist, 0x0001, 1); - new->last = aim_tlv_getstr(tlvlist, 0x0002, 1); - new->middle = aim_tlv_getstr(tlvlist, 0x0003, 1); - new->maiden = aim_tlv_getstr(tlvlist, 0x0004, 1); - new->email = aim_tlv_getstr(tlvlist, 0x0005, 1); - new->country = aim_tlv_getstr(tlvlist, 0x0006, 1); - new->state = aim_tlv_getstr(tlvlist, 0x0007, 1); - new->city = aim_tlv_getstr(tlvlist, 0x0008, 1); - new->bn = aim_tlv_getstr(tlvlist, 0x0009, 1); - new->interest = aim_tlv_getstr(tlvlist, 0x000b, 1); - new->nick = aim_tlv_getstr(tlvlist, 0x000c, 1); - new->zip = aim_tlv_getstr(tlvlist, 0x000d, 1); - new->region = aim_tlv_getstr(tlvlist, 0x001c, 1); - new->address = aim_tlv_getstr(tlvlist, 0x0021, 1); - new->next = results; - results = new; - numresults--; - } - - if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) - ret = userfunc(od, conn, frame, results); - - /* Now free everything from above */ - while (results) { - struct aim_odir *del = results; - results = results->next; - g_free(del->first); - g_free(del->last); - g_free(del->middle); - g_free(del->maiden); - g_free(del->email); - g_free(del->country); - g_free(del->state); - g_free(del->city); - g_free(del->bn); - g_free(del->interest); - g_free(del->nick); - g_free(del->zip); - g_free(del->region); - g_free(del->address); - g_free(del); - } - - return ret; -} - -static int -snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) -{ - if (snac->subtype == 0x0003) - return parseresults(od, conn, mod, frame, snac, bs); - - return 0; -} - -int -odir_modfirst(OscarData *od, aim_module_t *mod) -{ - mod->family = SNAC_FAMILY_ODIR; - mod->version = 0x0001; - mod->toolid = 0x0010; - mod->toolversion = 0x0629; - mod->flags = 0; - strncpy(mod->name, "odir", sizeof(mod->name)); - mod->snachandler = snachandler; - - return 0; -}
--- a/libpurple/protocols/oscar/family_oservice.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/family_oservice.c Thu Jul 29 00:06:56 2010 +0000 @@ -97,7 +97,7 @@ { int group; - while (byte_stream_empty(bs)) + while (byte_stream_bytes_left(bs)) { group = byte_stream_get16(bs); conn->groups = g_slist_prepend(conn->groups, GUINT_TO_POINTER(group)); @@ -449,29 +449,6 @@ byte_stream_destroy(&bs); } -/* Subtype 0x0009 - Delete Rate Parameter */ -void -aim_srv_rates_delparam(OscarData *od, FlapConnection *conn) -{ - ByteStream bs; - aim_snacid_t snacid; - GSList *tmp; - - byte_stream_new(&bs, 502); - - for (tmp = conn->rateclasses; tmp != NULL; tmp = tmp->next) - { - struct rateclass *rateclass; - rateclass = tmp->data; - byte_stream_put16(&bs, rateclass->classid); - } - - snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x0009, 0x0000, NULL, 0); - flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x0009, 0x0000, snacid, &bs); - - byte_stream_destroy(&bs); -} - /* Subtype 0x000a - Rate Change */ static int ratechange(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) @@ -558,40 +535,6 @@ return ret; } -/* - * Subtype 0x000c - Service Pause Acknowledgement - * - * It is rather important that aim_srv_sendpauseack() gets called for the exact - * same connection that the Server Pause callback was called for, since - * libfaim extracts the data for the SNAC from the connection structure. - * - * Of course, if you don't do that, more bad things happen than just what - * libfaim can cause. - * - */ -void -aim_srv_sendpauseack(OscarData *od, FlapConnection *conn) -{ - ByteStream bs; - aim_snacid_t snacid; - GSList *cur; - - byte_stream_new(&bs, 1014); - - /* - * This list should have all the groups that the original - * Host Online / Server Ready said this host supports. And - * we want them all back after the migration. - */ - for (cur = conn->groups; cur != NULL; cur = cur->next) - byte_stream_put16(&bs, GPOINTER_TO_UINT(cur->data)); - - snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x000c, 0x0000, NULL, 0); - flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x000c, 0x0000, snacid, &bs); - - byte_stream_destroy(&bs); -} - /* Subtype 0x000d - Service Resume */ static int serverresume(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) @@ -643,7 +586,7 @@ newevil = byte_stream_get16(bs); - if (byte_stream_empty(bs)) + if (byte_stream_bytes_left(bs)) aim_info_extract(od, bs, &userinfo); if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) @@ -770,36 +713,6 @@ } /* - * Subtype 0x0014 - Set privacy flags - * - * Normally 0x03. - * - * Bit 1: Allows other AIM users to see how long you've been idle. - * Bit 2: Allows other AIM users to see how long you've been a member. - * - */ -void -aim_srv_setprivacyflags(OscarData *od, FlapConnection *conn, guint32 flags) -{ - aim_genericreq_l(od, conn, SNAC_FAMILY_OSERVICE, 0x0014, &flags); -} - -/* - * Subtype 0x0016 - No-op - * - * WinAIM sends these every 4min or so to keep the connection alive. Its not - * really necessary. - * - * Wha? No? Since when? I think WinAIM sends an empty channel 5 - * FLAP as a no-op... - */ -void -aim_srv_nop(OscarData *od, FlapConnection *conn) -{ - aim_genericreq_n(od, conn, SNAC_FAMILY_OSERVICE, 0x0016); -} - -/* * Subtype 0x0017 - Set client versions * * If you've seen the clientonline/clientready SNAC you're probably @@ -850,8 +763,8 @@ guint8 *versions; /* This is frivolous. (Thank you SmarterChild.) */ - vercount = byte_stream_empty(bs)/4; - versions = byte_stream_getraw(bs, byte_stream_empty(bs)); + vercount = byte_stream_bytes_left(bs)/4; + versions = byte_stream_getraw(bs, byte_stream_bytes_left(bs)); g_free(versions); /* @@ -899,16 +812,6 @@ AIM_ICQ_STATE_HIDEIP | AIM_ICQ_STATE_DIRECTREQUIREAUTH); } -#if 0 - if (other_stuff_that_isnt_implemented) - { - aim_tlvlist_add_raw(&tlvlist, 0x000c, 0x0025, - chunk_of_x25_bytes_with_ip_address_etc); - aim_tlvlist_add_raw(&tlvlist, 0x0011, 0x0005, unknown 0x01 61 10 f6 41); - aim_tlvlist_add_16(&tlvlist, 0x0012, unknown 0x00 00); - } -#endif - if (setstatusmsg) { size_t statusmsglen, itmsurllen;
--- a/libpurple/protocols/oscar/family_translate.c Thu Jul 08 17:00:45 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* - * Purple's oscar protocol plugin - * This file is the legal property of its developers. - * Please see the AUTHORS file distributed alongside this file. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA -*/ - -/* - * Family 0x000c - Translation. - * - * I have no idea why this group was issued. I have never seen anything - * that uses it. From what I remember, the last time I tried to poke at - * the server with this group, it whined about not supporting it. - * - * But we advertise it anyway, because its fun. - * - */ - -#include "oscar.h" - -int translate_modfirst(OscarData *od, aim_module_t *mod) -{ - - mod->family = SNAC_FAMILY_TRANSLATE; - mod->version = 0x0001; - mod->toolid = 0x0104; - mod->toolversion = 0x0001; - mod->flags = 0; - strncpy(mod->name, "translate", sizeof(mod->name)); - mod->snachandler = NULL; - - return 0; -}
--- a/libpurple/protocols/oscar/flap_connection.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/flap_connection.c Thu Jul 29 00:06:56 2010 +0000 @@ -733,7 +733,7 @@ aim_module_t *cur; aim_modsnac_t snac; - if (byte_stream_empty(&frame->data) < 10) + if (byte_stream_bytes_left(&frame->data) < 10) return; snac.family = byte_stream_get16(&frame->data); @@ -800,7 +800,7 @@ GSList *tlvlist; char *msg = NULL; - if (byte_stream_empty(&frame->data) == 0) { + if (byte_stream_bytes_left(&frame->data) == 0) { /* XXX should do something with this */ return; } @@ -931,18 +931,6 @@ break; } - /* Verify the sequence number sent by the server. */ -#if 0 - /* TODO: Need to initialize conn->seqnum_in somewhere before we can use this. */ - if (aimutil_get16(&conn->header[1]) != conn->seqnum_in++) - { - /* Received an out-of-order FLAP! */ - flap_connection_schedule_destroy(conn, - OSCAR_DISCONNECT_INVALID_DATA, NULL); - break; - } -#endif - /* Initialize a new temporary FlapFrame for incoming data */ conn->buffer_incoming.channel = aimutil_get8(&conn->header[1]); conn->buffer_incoming.seqnum = aimutil_get16(&conn->header[2]); @@ -1074,8 +1062,8 @@ return; /* Make sure we don't send past the end of the bs */ - if (count > byte_stream_empty(bs)) - count = byte_stream_empty(bs); /* truncate to remaining space */ + if (count > byte_stream_bytes_left(bs)) + count = byte_stream_bytes_left(bs); /* truncate to remaining space */ if (count == 0) return;
--- a/libpurple/protocols/oscar/misc.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/misc.c Thu Jul 29 00:06:56 2010 +0000 @@ -77,29 +77,6 @@ byte_stream_destroy(&bs); } -void -aim_genericreq_s(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype, guint16 *shortdata) -{ - ByteStream bs; - aim_snacid_t snacid; - - if (!shortdata) - { - aim_genericreq_n(od, conn, family, subtype); - return; - } - - byte_stream_new(&bs, 2); - - snacid = aim_cachesnac(od, family, subtype, 0x0000, NULL, 0); - - byte_stream_put16(&bs, *shortdata); - - flap_connection_send_snac(od, conn, family, subtype, 0x0000, snacid, &bs); - - byte_stream_destroy(&bs); -} - /* * Should be generic enough to handle the errors for all groups. * @@ -114,7 +91,7 @@ snac2 = aim_remsnac(od, snac->id); - if (byte_stream_empty(bs)) + if (byte_stream_bytes_left(bs)) error = byte_stream_get16(bs); if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
--- a/libpurple/protocols/oscar/msgcookie.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/msgcookie.c Thu Jul 29 00:06:56 2010 +0000 @@ -177,18 +177,3 @@ return 0; } - -/* XXX I hate switch */ -int aim_msgcookie_gettype(guint64 type) -{ - /* XXX: hokey-assed. needs fixed. */ - switch(type) { - case OSCAR_CAPABILITY_BUDDYICON: return AIM_COOKIETYPE_OFTICON; - case OSCAR_CAPABILITY_TALK: return AIM_COOKIETYPE_OFTVOICE; - case OSCAR_CAPABILITY_DIRECTIM: return AIM_COOKIETYPE_OFTIMAGE; - case OSCAR_CAPABILITY_CHAT: return AIM_COOKIETYPE_CHAT; - case OSCAR_CAPABILITY_GETFILE: return AIM_COOKIETYPE_OFTGET; - case OSCAR_CAPABILITY_SENDFILE: return AIM_COOKIETYPE_OFTSEND; - default: return AIM_COOKIETYPE_UNKNOWN; - } -}
--- a/libpurple/protocols/oscar/odc.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/odc.c Thu Jul 29 00:06:56 2010 +0000 @@ -19,6 +19,7 @@ */ /* From the oscar PRPL */ +#include "encoding.h" #include "oscar.h" #include "peer.h" @@ -366,8 +367,7 @@ g_datalist_clear(&attributes); /* Append the message up to the tag */ - utf8 = purple_plugin_oscar_decode_im_part(account, conn->bn, - encoding, 0x0000, tmp, start - tmp); + utf8 = oscar_decode_im(account, conn->bn, encoding, tmp, start - tmp); if (utf8 != NULL) { g_string_append(newmsg, utf8); g_free(utf8); @@ -386,8 +386,7 @@ /* Append any remaining message data */ if (tmp <= msgend) { - utf8 = purple_plugin_oscar_decode_im_part(account, conn->bn, - encoding, 0x0000, tmp, msgend - tmp); + utf8 = oscar_decode_im(account, conn->bn, encoding, tmp, msgend - tmp); if (utf8 != NULL) { g_string_append(newmsg, utf8); g_free(utf8);
--- a/libpurple/protocols/oscar/oscar.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/oscar.c Thu Jul 29 00:06:56 2010 +0000 @@ -37,6 +37,7 @@ #include "conversation.h" #include "core.h" #include "debug.h" +#include "encoding.h" #include "imgstore.h" #include "network.h" #include "notify.h" @@ -107,8 +108,6 @@ static int purple_conv_chat_incoming_msg(OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_email_parseupdate(OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_icon_parseicon (OscarData *, FlapConnection *, FlapFrame *, ...); -static int purple_parse_msgack (OscarData *, FlapConnection *, FlapFrame *, ...); -static int purple_parse_evilnotify (OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_parse_searcherror(OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_parse_searchreply(OscarData *, FlapConnection *, FlapFrame *, ...); static int purple_bosrights (OscarData *, FlapConnection *, FlapFrame *, ...); @@ -152,368 +151,6 @@ } #endif -/** - * 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. - */ -static guint32 -oscar_charset_check(const char *utf8) -{ - int i = 0; - int charset = AIM_CHARSET_ASCII; - - /* - * Can we get away with using our custom encoding? - */ - while (utf8[i]) - { - if ((unsigned char)utf8[i] > 0x7f) { - /* not ASCII! */ - charset = AIM_CHARSET_LATIN_1; - break; - } - i++; - } - - /* - * Must we send this message as UNICODE (in the UTF-16BE encoding)? - */ - 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; - } - charset = AIM_CHARSET_UNICODE; - break; - } - - return charset; -} - -/** - * Take a string of the form charset="bleh" where bleh is - * one of us-ascii, utf-8, iso-8859-1, or unicode-2-0, and - * return a newly allocated string containing bleh. - */ -gchar * -oscar_encoding_extract(const char *encoding) -{ - gchar *ret = NULL; - char *begin, *end; - - g_return_val_if_fail(encoding != NULL, NULL); - - /* Make sure encoding begins with charset= */ - if (strncmp(encoding, "text/aolrtf; charset=", 21) && - strncmp(encoding, "text/x-aolrtf; charset=", 23) && - strncmp(encoding, "text/plain; charset=", 20)) - { - return NULL; - } - - begin = strchr(encoding, '"'); - end = strrchr(encoding, '"'); - - if ((begin == NULL) || (end == NULL) || (begin >= end)) - return NULL; - - ret = g_strndup(begin+1, (end-1) - begin); - - return ret; -} - -gchar * -oscar_encoding_to_utf8(PurpleAccount *account, const char *encoding, const char *text, int textlen) -{ - gchar *utf8 = NULL; - - if ((encoding == NULL) || encoding[0] == '\0') { - purple_debug_info("oscar", "Empty encoding, assuming UTF-8\n"); - } else if (!g_ascii_strcasecmp(encoding, "iso-8859-1")) { - utf8 = g_convert(text, textlen, "UTF-8", "iso-8859-1", NULL, NULL, NULL); - } else if (!g_ascii_strcasecmp(encoding, "ISO-8859-1-Windows-3.1-Latin-1") || - !g_ascii_strcasecmp(encoding, "us-ascii")) - { - utf8 = g_convert(text, textlen, "UTF-8", "Windows-1252", NULL, NULL, NULL); - } else if (!g_ascii_strcasecmp(encoding, "unicode-2-0")) { - /* Some official ICQ clients are apparently total crack, - * and have been known to save a UTF-8 string converted - * from the locale character set to UTF-16 (not from UTF-8 - * to UTF-16!) in the away message. This hack should find - * and do something (un)reasonable with that, and not - * mess up too much else. */ - const gchar *charset = purple_account_get_string(account, "encoding", NULL); - if (charset) { - gsize len; - utf8 = g_convert(text, textlen, charset, "UTF-16BE", &len, NULL, NULL); - if (!utf8 || len != textlen || !g_utf8_validate(utf8, -1, NULL)) { - g_free(utf8); - utf8 = NULL; - } else { - purple_debug_info("oscar", "Used broken ICQ fallback encoding\n"); - } - } - if (!utf8) - utf8 = g_convert(text, textlen, "UTF-8", "UTF-16BE", NULL, NULL, NULL); - } else if (g_ascii_strcasecmp(encoding, "utf-8")) { - purple_debug_warning("oscar", "Unrecognized character encoding \"%s\", " - "attempting to convert to UTF-8 anyway\n", encoding); - utf8 = g_convert(text, textlen, "UTF-8", encoding, NULL, NULL, NULL); - } - - /* - * If utf8 is still NULL then either the encoding is utf-8 or - * we have been unable to convert the text to utf-8 from the encoding - * that was specified. So we check if the text is valid utf-8 then - * just copy it. - */ - if (utf8 == NULL) { - if (textlen != 0 && *text != '\0' - && !g_utf8_validate(text, textlen, NULL)) - utf8 = g_strdup(_("(There was an error receiving this message. The buddy you are speaking with is probably using a different encoding than expected. If you know what encoding he is using, you can specify it in the advanced account options for your AIM/ICQ account.)")); - else - utf8 = g_strndup(text, textlen); - } - - return utf8; -} - -gchar * -oscar_utf8_try_convert(PurpleAccount *account, OscarData *od, const gchar *msg) -{ - const char *charset = NULL; - char *ret = NULL; - - if (od->icq) - charset = purple_account_get_string(account, "encoding", NULL); - - if(charset && *charset) - ret = g_convert(msg, -1, "UTF-8", charset, NULL, NULL, NULL); - - if(!ret) - ret = purple_utf8_try_convert(msg); - - return ret; -} - -static gchar * -purple_plugin_oscar_convert_to_utf8(const gchar *data, gsize datalen, const char *charsetstr, gboolean fallback) -{ - gchar *ret = NULL; - GError *err = NULL; - - if ((charsetstr == NULL) || (*charsetstr == '\0')) - return NULL; - - if (g_ascii_strcasecmp("UTF-8", charsetstr)) { - if (fallback) - ret = g_convert_with_fallback(data, datalen, "UTF-8", charsetstr, "?", NULL, NULL, &err); - else - ret = g_convert(data, datalen, "UTF-8", charsetstr, NULL, NULL, &err); - if (err != NULL) { - purple_debug_warning("oscar", "Conversion from %s failed: %s.\n", - charsetstr, err->message); - g_error_free(err); - } - } else { - if (g_utf8_validate(data, datalen, NULL)) - ret = g_strndup(data, datalen); - else - purple_debug_warning("oscar", "String is not valid UTF-8.\n"); - } - - return ret; -} - -/** - * This attemps to decode an incoming IM into a UTF8 string. - * - * We try decoding using two different character sets. The charset - * specified in the IM determines the order in which we attempt to - * decode. We do this because there are lots of broken ICQ clients - * that don't correctly send non-ASCII messages. And if Purple isn't - * able to deal with that crap, then people complain like banshees. - * charsetstr1 is always set to what the correct encoding should be. - */ -gchar * -purple_plugin_oscar_decode_im_part(PurpleAccount *account, const char *sourcebn, guint16 charset, guint16 charsubset, const gchar *data, gsize datalen) -{ - gchar *ret = NULL; - const gchar *charsetstr1, *charsetstr2, *charsetstr3 = NULL; - - if ((datalen == 0) || (data == NULL)) - return NULL; - - if (charset == AIM_CHARSET_UNICODE) { - charsetstr1 = "UTF-16BE"; - charsetstr2 = "UTF-8"; - } else if (charset == AIM_CHARSET_LATIN_1) { - if ((sourcebn != NULL) && oscar_util_valid_name_icq(sourcebn)) - charsetstr1 = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING); - else - charsetstr1 = "ISO-8859-1"; - charsetstr2 = "UTF-8"; - } else if (charset == AIM_CHARSET_ASCII) { - /* Should just be "ASCII" */ - charsetstr1 = "ASCII"; - charsetstr2 = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING); - } else if (charset == 0x000d) { - /* iChat sending unicode over a Direct IM connection = UTF-8 */ - /* Mobile AIM client on multiple devices (including Blackberry Tour, Nokia 3100, and LG VX6000) = ISO-8859-1 */ - charsetstr1 = "UTF-8"; - charsetstr2 = "ISO-8859-1"; - charsetstr3 = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING); - } else { - /* Unknown, hope for valid UTF-8... */ - charsetstr1 = "UTF-8"; - charsetstr2 = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING); - } - - purple_debug_info("oscar", "Parsing IM part, charset=0x%04hx, charsubset=0x%04hx, datalen=%" G_GSIZE_FORMAT ", choice1=%s, choice2=%s, choice3=%s\n", - charset, charsubset, datalen, charsetstr1, charsetstr2, (charsetstr3 ? charsetstr3 : "")); - - ret = purple_plugin_oscar_convert_to_utf8(data, datalen, charsetstr1, FALSE); - if (ret == NULL) { - if (charsetstr3 != NULL) { - /* Try charsetstr2 without allowing substitutions, then fall through to charsetstr3 if needed */ - ret = purple_plugin_oscar_convert_to_utf8(data, datalen, charsetstr2, FALSE); - if (ret == NULL) - ret = purple_plugin_oscar_convert_to_utf8(data, datalen, charsetstr3, TRUE); - } else { - /* Try charsetstr2, allowing substitutions */ - ret = purple_plugin_oscar_convert_to_utf8(data, datalen, charsetstr2, TRUE); - } - } - if (ret == NULL) { - char *str, *salvage, *tmp; - - str = g_malloc(datalen + 1); - strncpy(str, data, datalen); - str[datalen] = '\0'; - salvage = purple_utf8_salvage(str); - tmp = g_strdup_printf(_("(There was an error receiving this message. Either you and %s have different encodings selected, or %s has a buggy client.)"), - sourcebn, sourcebn); - ret = g_strdup_printf("%s %s", salvage, tmp); - g_free(tmp); - g_free(str); - g_free(salvage); - } - - return ret; -} - -/** - * Figure out what encoding to use when sending a given outgoing message. - */ -static void -purple_plugin_oscar_convert_to_best_encoding(PurpleConnection *gc, - const char *destbn, const gchar *from, - gchar **msg, int *msglen_int, - guint16 *charset, guint16 *charsubset) -{ - OscarData *od = purple_connection_get_protocol_data(gc); - PurpleAccount *account = purple_connection_get_account(gc); - GError *err = NULL; - aim_userinfo_t *userinfo = NULL; - const gchar *charsetstr; - gsize msglen; - - /* Attempt to send as ASCII */ - if (oscar_charset_check(from) == AIM_CHARSET_ASCII) { - *msg = g_convert(from, -1, "ASCII", "UTF-8", NULL, &msglen, NULL); - *charset = AIM_CHARSET_ASCII; - *charsubset = 0x0000; - *msglen_int = msglen; - return; - } - - /* - * If we're sending to an ICQ user, and they are in our - * buddy list, and they are advertising the Unicode - * capability, and they are online, then attempt to send - * as UTF-16BE. - */ - if ((destbn != NULL) && oscar_util_valid_name_icq(destbn)) - userinfo = aim_locate_finduserinfo(od, destbn); - - if ((userinfo != NULL) && (userinfo->capabilities & OSCAR_CAPABILITY_UNICODE)) - { - PurpleBuddy *b; - b = purple_find_buddy(account, destbn); - if ((b != NULL) && (PURPLE_BUDDY_IS_ONLINE(b))) - { - *msg = g_convert(from, -1, "UTF-16BE", "UTF-8", NULL, &msglen, &err); - if (*msg != NULL) - { - *charset = AIM_CHARSET_UNICODE; - *charsubset = 0x0000; - *msglen_int = msglen; - return; - } - - purple_debug_error("oscar", "Conversion from UTF-8 to UTF-16BE failed: %s.\n", - err->message); - g_error_free(err); - err = NULL; - } - } - - /* - * If this is AIM then attempt to send as ISO-8859-1. If this is - * ICQ then attempt to send as the user specified character encoding. - */ - charsetstr = "ISO-8859-1"; - if ((destbn != NULL) && oscar_util_valid_name_icq(destbn)) - charsetstr = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING); - - /* - * XXX - We need a way to only attempt to convert if we KNOW "from" - * can be converted to "charsetstr" - */ - *msg = g_convert(from, -1, charsetstr, "UTF-8", NULL, &msglen, &err); - if (*msg != NULL) { - *charset = AIM_CHARSET_LATIN_1; - *charsubset = 0x0000; - *msglen_int = msglen; - return; - } - - purple_debug_info("oscar", "Conversion from UTF-8 to %s failed (%s). Falling back to unicode.\n", - charsetstr, err->message); - g_error_free(err); - err = NULL; - - /* - * Nothing else worked, so send as UTF-16BE. - */ - *msg = g_convert(from, -1, "UTF-16BE", "UTF-8", NULL, &msglen, &err); - if (*msg != NULL) { - *charset = AIM_CHARSET_UNICODE; - *charsubset = 0x0000; - *msglen_int = msglen; - return; - } - - purple_debug_error("oscar", "Error converting a Unicode message: %s\n", err->message); - g_error_free(err); - err = NULL; - - purple_debug_error("oscar", "This should NEVER happen! Sending UTF-8 text flagged as ASCII.\n"); - *msg = g_strdup(from); - *msglen_int = strlen(*msg); - *charset = AIM_CHARSET_ASCII; - *charsubset = 0x0000; - return; -} - static char *oscar_icqstatus(int state) { /* Make a cute little string that shows the status of the dude or dudet */ if (state & AIM_ICQ_STATE_CHAT) @@ -1027,14 +664,12 @@ oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_MISSEDCALL, purple_parse_misses, 0); oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_CLIENTAUTORESP, purple_parse_clientauto, 0); oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_MTN, purple_parse_mtn, 0); - oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_ACK, purple_parse_msgack, 0); oscar_data_addhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_RIGHTSINFO, purple_parse_locaterights, 0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x0001, purple_parse_genericerr, 0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x000f, purple_selfinfo, 0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x001f, purple_memrequest, 0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_REDIRECT, purple_handle_redirect, 0); oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_MOTD, purple_parse_motd, 0); - oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_EVIL, purple_parse_evilnotify, 0); oscar_data_addhandler(od, SNAC_FAMILY_POPUP, 0x0002, purple_popup, 0); oscar_data_addhandler(od, SNAC_FAMILY_USERLOOKUP, SNAC_SUBTYPE_USERLOOKUP_ERROR, purple_parse_searcherror, 0); oscar_data_addhandler(od, SNAC_FAMILY_USERLOOKUP, 0x0003, purple_parse_searchreply, 0); @@ -1294,34 +929,6 @@ AIM_SENDMEMBLOCK_FLAG_ISREQUEST); return 1; } - /* uncomment this when you're convinced it's right. remember, it's been wrong before. */ -#if 0 - if (offset > AIM_MAX_FILE_SIZE || len > AIM_MAX_FILE_SIZE) { - char *buf; - int i = 8; - if (modname) - i += strlen(modname); - buf = g_malloc(i); - i = 0; - if (modname) { - memcpy(buf, modname, strlen(modname)); - i += strlen(modname); - } - buf[i++] = offset & 0xff; - buf[i++] = (offset >> 8) & 0xff; - buf[i++] = (offset >> 16) & 0xff; - buf[i++] = (offset >> 24) & 0xff; - buf[i++] = len & 0xff; - buf[i++] = (len >> 8) & 0xff; - buf[i++] = (len >> 16) & 0xff; - buf[i++] = (len >> 24) & 0xff; - purple_debug_misc("oscar", "len + offset is invalid, " - "hashing request\n"); - aim_sendmemblock(od, command->conn, offset, i, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST); - g_free(buf); - return 1; - } -#endif pos = g_new0(struct pieceofcrap, 1); pos->gc = od->gc; @@ -1776,18 +1383,18 @@ purple_prpl_got_user_status_deactive(account, info->bn, OSCAR_STATUS_ID_MOBILE); } - if (info->status != NULL && info->status[0] != '\0') + if (info->status != NULL && info->status[0] != '\0') { /* Grab the available message */ - message = oscar_encoding_to_utf8(account, info->status_encoding, - info->status, info->status_len); + message = oscar_encoding_to_utf8(info->status_encoding, info->status, info->status_len); + } tmp2 = tmp = (message ? purple_markup_escape_text(message, -1) : NULL); if (strcmp(status_id, OSCAR_STATUS_ID_AVAILABLE) == 0) { - if (info->itmsurl_encoding && info->itmsurl && info->itmsurl_len) + if (info->itmsurl_encoding && info->itmsurl && info->itmsurl_len) { /* Grab the iTunes Music Store URL */ - itmsurl = oscar_encoding_to_utf8(account, info->itmsurl_encoding, - info->itmsurl, info->itmsurl_len); + itmsurl = oscar_encoding_to_utf8(info->itmsurl_encoding, info->itmsurl, info->itmsurl_len); + } if (tmp2 == NULL && itmsurl != NULL) /* @@ -1893,17 +1500,11 @@ PurpleMessageFlags flags = 0; struct buddyinfo *bi; PurpleStoredImage *img; - GString *message; gchar *tmp; - aim_mpmsg_section_t *curpart; const char *start, *end; GData *attribs; - purple_debug_misc("oscar", "Received IM from %s with %d parts\n", - userinfo->bn, args->mpmsg.numparts); - - if (args->mpmsg.numparts == 0) - return 1; + purple_debug_misc("oscar", "Received IM from %s\n", userinfo->bn); bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, userinfo->bn)); if (!bi) { @@ -1943,19 +1544,7 @@ } purple_imgstore_unref(img); - message = g_string_new(""); - curpart = args->mpmsg.parts; - while (curpart != NULL) { - tmp = purple_plugin_oscar_decode_im_part(account, userinfo->bn, curpart->charset, - curpart->charsubset, curpart->data, curpart->datalen); - if (tmp != NULL) { - g_string_append(message, tmp); - g_free(tmp); - } - - curpart = curpart->next; - } - tmp = g_string_free(message, FALSE); + tmp = g_strdup(args->msg); /* * Convert iChat color tags to normal font tags. @@ -2039,8 +1628,7 @@ tmp = tmp2; } - serv_got_im(gc, userinfo->bn, tmp, flags, - (args->icbmflags & AIM_IMFLAGS_OFFLINE) ? args->timestamp : time(NULL)); + serv_got_im(gc, userinfo->bn, tmp, flags, (args->icbmflags & AIM_IMFLAGS_OFFLINE) ? args->timestamp : time(NULL)); g_free(tmp); return 1; @@ -2068,35 +1656,20 @@ G_GUINT64_FORMAT ", user %s, status %hu\n", args->type, userinfo->bn, args->status); - if (args->msg != NULL) - { - if (args->encoding != NULL) - { - char *encoding = NULL; - encoding = oscar_encoding_extract(args->encoding); - message = oscar_encoding_to_utf8(account, encoding, args->msg, - args->msglen); - g_free(encoding); - } else { - if (g_utf8_validate(args->msg, args->msglen, NULL)) - message = g_strdup(args->msg); - } + if (args->msg != NULL) { + message = oscar_encoding_to_utf8(args->encoding, args->msg, args->msglen); } if (args->type & OSCAR_CAPABILITY_CHAT) { - char *encoding, *utf8name, *tmp; + char *utf8name, *tmp; GHashTable *components; if (!args->info.chat.roominfo.name || !args->info.chat.roominfo.exchange) { g_free(message); return 1; } - encoding = args->encoding ? oscar_encoding_extract(args->encoding) : NULL; - utf8name = oscar_encoding_to_utf8(account, encoding, - args->info.chat.roominfo.name, - args->info.chat.roominfo.namelen); - g_free(encoding); + utf8name = oscar_encoding_to_utf8(args->encoding, args->info.chat.roominfo.name, args->info.chat.roominfo.namelen); tmp = extract_name(utf8name); if (tmp != NULL) @@ -2117,8 +1690,7 @@ components); } - else if ((args->type & OSCAR_CAPABILITY_SENDFILE) || - (args->type & OSCAR_CAPABILITY_DIRECTIM)) + else if ((args->type & OSCAR_CAPABILITY_SENDFILE) || (args->type & OSCAR_CAPABILITY_DIRECTIM)) { if (args->status == AIM_RENDEZVOUS_PROPOSE) { @@ -2171,24 +1743,11 @@ purple_debug_info("oscar", "Got an ICQ Server Relay message of " "type %d\n", args->info.rtfmsg.msgtype); - if (args->info.rtfmsg.msgtype == 1) - { - if (args->info.rtfmsg.rtfmsg != NULL) - { - char *rtfmsg = NULL; - if (args->encoding != NULL) { - char *encoding = oscar_encoding_extract(args->encoding); - rtfmsg = oscar_encoding_to_utf8(account, encoding, - args->info.rtfmsg.rtfmsg, strlen(args->info.rtfmsg.rtfmsg)); - g_free(encoding); - } else { - if (g_utf8_validate(args->info.rtfmsg.rtfmsg, strlen(args->info.rtfmsg.rtfmsg), NULL)) - rtfmsg = g_strdup(args->info.rtfmsg.rtfmsg); - } - if (rtfmsg) { - serv_got_im(gc, userinfo->bn, rtfmsg, flags, time(NULL)); - g_free(rtfmsg); - } + if (args->info.rtfmsg.msgtype == 1) { + if (args->info.rtfmsg.msg != NULL) { + char *rtfmsg = oscar_encoding_to_utf8(args->encoding, args->info.rtfmsg.msg, strlen(args->info.rtfmsg.msg)); + serv_got_im(gc, userinfo->bn, rtfmsg, flags, time(NULL)); + g_free(rtfmsg); } } else if (args->info.rtfmsg.msgtype == 26) { purple_debug_info("oscar", "Sending X-Status Reply\n"); @@ -2249,7 +1808,7 @@ purple_str_strip_char(msg1[i], '\r'); /* TODO: Should use an encoding other than ASCII? */ - msg2[i] = purple_plugin_oscar_decode_im_part(account, uin, AIM_CHARSET_ASCII, 0x0000, msg1[i], strlen(msg1[i])); + msg2[i] = oscar_decode_im(account, uin, AIM_CHARSET_ASCII, msg1[i], strlen(msg1[i])); g_free(uin); } msg2[i] = NULL; @@ -2306,7 +1865,7 @@ gchar *reason = NULL; if (msg2[5] != NULL) - reason = purple_plugin_oscar_decode_im_part(account, bn, AIM_CHARSET_LATIN_1, 0x0000, msg2[5], strlen(msg2[5])); + reason = oscar_decode_im(account, bn, AIM_CHARSET_LATIN_1, msg2[5], strlen(msg2[5])); purple_debug_info("oscar", "Received an authorization request from UIN %u\n", @@ -2906,13 +2465,7 @@ static int purple_conv_chat_info_update(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { va_list ap; - aim_userinfo_t *userinfo; - struct aim_chat_roominfo *roominfo; - char *roomname; - int usercount; - char *roomdesc; - guint16 unknown_c9, unknown_d2, unknown_d5, maxmsglen, maxvisiblemsglen; - guint32 creationtime; + guint16 maxmsglen, maxvisiblemsglen; PurpleConnection *gc = od->gc; struct chat_connection *ccon = find_oscar_chat_by_conn(gc, conn); @@ -2920,16 +2473,7 @@ return 1; va_start(ap, fr); - roominfo = va_arg(ap, struct aim_chat_roominfo *); - roomname = va_arg(ap, char *); - usercount= va_arg(ap, int); - userinfo = va_arg(ap, aim_userinfo_t *); - roomdesc = va_arg(ap, char *); - unknown_c9 = (guint16)va_arg(ap, unsigned int); - creationtime = va_arg(ap, guint32); maxmsglen = (guint16)va_arg(ap, unsigned int); - unknown_d2 = (guint16)va_arg(ap, unsigned int); - unknown_d5 = (guint16)va_arg(ap, unsigned int); maxvisiblemsglen = (guint16)va_arg(ap, unsigned int); va_end(ap); @@ -2945,7 +2489,6 @@ static int purple_conv_chat_incoming_msg(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { PurpleConnection *gc = od->gc; - PurpleAccount *account = purple_connection_get_account(gc); struct chat_connection *ccon = find_oscar_chat_by_conn(gc, conn); gchar *utf8; va_list ap; @@ -2964,10 +2507,7 @@ charset = va_arg(ap, char *); va_end(ap); - utf8 = oscar_encoding_to_utf8(account, charset, msg, len); - if (utf8 == NULL) - /* The conversion failed! */ - utf8 = g_strdup(_("[Unable to display a message from this user because it contained invalid characters.]")); + utf8 = oscar_encoding_to_utf8(charset, msg, len); serv_got_chat_in(gc, ccon->id, info->bn, 0, utf8, time(NULL)); g_free(utf8); @@ -3085,41 +2625,6 @@ purple_debug_misc("oscar", "no more icons to request\n"); } -/* - * Received in response to an IM sent with the AIM_IMFLAGS_ACK option. - */ -static int purple_parse_msgack(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { - va_list ap; - guint16 type; - char *bn; - - va_start(ap, fr); - type = (guint16) va_arg(ap, unsigned int); - bn = va_arg(ap, char *); - va_end(ap); - - purple_debug_info("oscar", "Sent message to %s.\n", bn); - - return 1; -} - -static int purple_parse_evilnotify(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { -#ifdef CRAZY_WARNING - va_list ap; - guint16 newevil; - aim_userinfo_t *userinfo; - - va_start(ap, fr); - newevil = (guint16) va_arg(ap, unsigned int); - userinfo = va_arg(ap, aim_userinfo_t *); - va_end(ap); - - purple_prpl_got_account_warning_level(account, (userinfo && userinfo->bn) ? userinfo->bn : NULL, (newevil/10.0) + 0.5); -#endif - - return 1; -} - static int purple_selfinfo(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { int warning_level; va_list ap; @@ -3140,10 +2645,6 @@ */ warning_level = info->warnlevel/10.0 + 0.5; -#ifdef CRAZY_WARNING - purple_presence_set_warning_level(presence, warning_level); -#endif - return 1; } @@ -3544,8 +3045,8 @@ GString *msg; GString *data; gchar *tmp; - int tmplen; - guint16 charset, charsubset; + gsize tmplen; + guint16 charset; GData *attribs; const char *start, *end, *last; int oscar_id = 0; @@ -3606,8 +3107,7 @@ g_string_append(msg, "</BODY></HTML>"); /* Convert the message to a good encoding */ - purple_plugin_oscar_convert_to_best_encoding(conn->od->gc, - conn->bn, msg->str, &tmp, &tmplen, &charset, &charsubset); + tmp = oscar_convert_to_best_encoding(msg->str, &tmplen, &charset, NULL); g_string_free(msg, TRUE); msg = g_string_new_len(tmp, tmplen); g_free(tmp); @@ -3687,7 +3187,7 @@ g_hash_table_insert(od->buddyinfo, g_strdup(purple_normalize(account, name)), bi); } - args.flags = AIM_IMFLAGS_ACK | AIM_IMFLAGS_CUSTOMFEATURES; + args.flags = 0; if (!is_sms && (!buddy || !PURPLE_BUDDY_IS_ONLINE(buddy))) args.flags |= AIM_IMFLAGS_OFFLINE; @@ -3756,7 +3256,7 @@ g_free(tmp1); tmp1 = tmp2; - purple_plugin_oscar_convert_to_best_encoding(gc, name, tmp1, (char **)&args.msg, &args.msglen, &args.charset, &args.charsubset); + args.msg = oscar_convert_to_best_encoding(tmp1, &args.msglen, &args.charset, NULL); if (is_html && (args.msglen > MAXMSGLEN)) { /* If the length was too long, try stripping the HTML and then running it back through * purple_strdup_withhtml() and the encoding process. The result may be shorter. */ @@ -3773,14 +3273,12 @@ g_free(tmp1); tmp1 = tmp2; - purple_plugin_oscar_convert_to_best_encoding(gc, name, tmp1, (char **)&args.msg, &args.msglen, &args.charset, &args.charsubset); - + args.msg = oscar_convert_to_best_encoding(tmp1, &args.msglen, &args.charset, NULL); purple_debug_info("oscar", "Sending %s as %s because the original was too long.\n", message, (char *)args.msg); } - purple_debug_info("oscar", "Sending IM, charset=0x%04hx, charsubset=0x%04hx, length=%d\n", - args.charset, args.charsubset, args.msglen); + purple_debug_info("oscar", "Sending IM, charset=0x%04hx, length=%" G_GSIZE_FORMAT "\n", args.charset, args.msglen); ret = aim_im_sendch1_ext(od, &args); g_free((char *)args.msg); } @@ -3807,43 +3305,11 @@ aim_locate_getinfoshort(od, name, 0x00000003); } -#if 0 -static void oscar_set_dir(PurpleConnection *gc, const char *first, const char *middle, const char *last, - const char *maiden, const char *city, const char *state, const char *country, int web) { - /* XXX - some of these things are wrong, but i'm lazy */ - OscarData *od = purple_connection_get_protocol_data(gc); - aim_locate_setdirinfo(od, first, middle, last, - maiden, NULL, NULL, city, state, NULL, 0, web); -} -#endif - void oscar_set_idle(PurpleConnection *gc, int time) { OscarData *od = purple_connection_get_protocol_data(gc); aim_srv_setidle(od, time); } -static -gchar *purple_prpl_oscar_convert_to_infotext(const gchar *str, gsize *ret_len, char **encoding) -{ - int charset = 0; - char *encoded = NULL; - - charset = oscar_charset_check(str); - if (charset == AIM_CHARSET_UNICODE) { - encoded = g_convert(str, -1, "UTF-16BE", "UTF-8", NULL, ret_len, NULL); - *encoding = "unicode-2-0"; - } else if (charset == AIM_CHARSET_LATIN_1) { - encoded = g_convert(str, -1, "ISO-8859-1", "UTF-8", NULL, ret_len, NULL); - *encoding = "iso-8859-1"; - } else { - encoded = g_strdup(str); - *ret_len = strlen(str); - *encoding = "us-ascii"; - } - - return encoded; -} - void oscar_set_info(PurpleConnection *gc, const char *rawinfo) { @@ -3947,7 +3413,7 @@ else if (rawinfo != NULL) { char *htmlinfo = purple_strdup_withhtml(rawinfo); - info = purple_prpl_oscar_convert_to_infotext(htmlinfo, &infolen, &info_encoding); + info = oscar_convert_to_best_encoding(htmlinfo, &infolen, NULL, &info_encoding); g_free(htmlinfo); if (infolen > od->rights.maxsiglen) @@ -3980,7 +3446,7 @@ /* We do this for icq too so that they work for old third party clients */ linkified = purple_markup_linkify(status_html); - away = purple_prpl_oscar_convert_to_infotext(linkified, &awaylen, &away_encoding); + away = oscar_convert_to_best_encoding(linkified, &awaylen, NULL, &away_encoding); g_free(linkified); if (awaylen > od->rights.maxawaymsglen) @@ -4076,14 +3542,6 @@ oscar_set_info_and_status(account, FALSE, NULL, TRUE, status); } -#ifdef CRAZY_WARN -void -oscar_warn(PurpleConnection *gc, const char *name, gboolean anonymous) { - OscarData *od = purple_connection_get_protocol_data(gc); - aim_im_warn(od, od->conn, name, anonymous ? AIM_WARN_ANON : 0); -} -#endif - void oscar_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) { OscarData *od; @@ -4952,9 +4410,9 @@ PurpleConversation *conv = NULL; struct chat_connection *c = NULL; char *buf, *buf2, *buf3; - guint16 charset, charsubset; - char *charsetstr = NULL; - int len; + guint16 charset; + char *charsetstr; + gsize len; if (!(conv = purple_find_chat(gc, id))) return -EINVAL; @@ -4970,7 +4428,7 @@ "You cannot send IM Images in AIM chats."), PURPLE_MESSAGE_ERROR, time(NULL)); - purple_plugin_oscar_convert_to_best_encoding(gc, NULL, buf, &buf2, &len, &charset, &charsubset); + buf2 = oscar_convert_to_best_encoding(buf, &len, &charset, &charsetstr); /* * Evan S. suggested that maxvis really does mean "number of * visible characters" and not "number of bytes" @@ -4986,10 +4444,11 @@ buf = purple_strdup_withhtml(buf3); g_free(buf3); - purple_plugin_oscar_convert_to_best_encoding(gc, NULL, buf, &buf2, &len, &charset, &charsubset); + buf2 = oscar_convert_to_best_encoding(buf, &len, &charset, &charsetstr); if ((len > c->maxlen) || (len > c->maxvis)) { - purple_debug_warning("oscar", "Could not send %s because (%i > maxlen %i) or (%i > maxvis %i)\n", + purple_debug_warning("oscar", + "Could not send %s because (%" G_GSIZE_FORMAT " > maxlen %i) or (%" G_GSIZE_FORMAT " > maxvis %i)\n", buf2, len, c->maxlen, len, c->maxvis); g_free(buf); g_free(buf2); @@ -5000,12 +4459,6 @@ message, buf2); } - if (charset == AIM_CHARSET_ASCII) - charsetstr = "us-ascii"; - else if (charset == AIM_CHARSET_UNICODE) - charsetstr = "unicode-2-0"; - else if (charset == AIM_CHARSET_LATIN_1) - charsetstr = "iso-8859-1"; aim_chat_send_im(od, c->conn, 0, buf2, len, charsetstr, "en"); g_free(buf2); g_free(buf); @@ -5605,15 +5058,6 @@ } menu = g_list_prepend(menu, act); } -#if 0 - /* TODO: This menu item should be added by the core */ - if (userinfo->capabilities & OSCAR_CAPABILITY_GETFILE) { - act = purple_menu_action_new(_("Get File"), - PURPLE_CALLBACK(oscar_ask_getfile), - NULL, NULL); - menu = g_list_prepend(menu, act); - } -#endif } if (od->ssi.received_data && purple_buddy_get_group(buddy) != NULL) @@ -6051,12 +5495,6 @@ oscar_show_find_email); menu = g_list_prepend(menu, act); -#if 0 - act = purple_plugin_action_new(_("Search for Buddy by Information"), - show_find_info); - menu = g_list_prepend(menu, act); -#endif - menu = g_list_reverse(menu); return menu;
--- a/libpurple/protocols/oscar/oscar.h Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/oscar.h Thu Jul 29 00:06:56 2010 +0000 @@ -103,16 +103,6 @@ #define AIM_ICONIDENT "AVT1picture.id" /* - * Current Maximum Length for Chat Room Messages - * - * This is actually defined by the protocol to be - * dynamic, but I have yet to see due cause to - * define it dynamically here. Maybe later. - * - */ -#define MAXCHATMSGLEN 512 - -/* * Found by trial and error. */ #define MAXAVAILMSGLEN 251 @@ -143,167 +133,6 @@ const char *lang; /* two-letter abbrev */ }; -/* Needs to be checked */ -#define CLIENTINFO_AIM_3_5_1670 { \ - "AOL Instant Messenger (SM), version 3.5.1670/WIN32", \ - 0x0004, \ - 0x0003, 0x0005, \ - 0x0000, 0x0686, \ - 0x0000002a, \ - "us", "en", \ -} - -/* Needs to be checked */ -/* Latest winaim without ssi */ -#define CLIENTINFO_AIM_4_1_2010 { \ - "AOL Instant Messenger (SM), version 4.1.2010/WIN32", \ - 0x0004, \ - 0x0004, 0x0001, \ - 0x0000, 0x07da, \ - 0x0000004b, \ - "us", "en", \ -} - -/* Needs to be checked */ -#define CLIENTINFO_AIM_4_3_2188 { \ - "AOL Instant Messenger (SM), version 4.3.2188/WIN32", \ - 0x0109, \ - 0x0400, 0x0003, \ - 0x0000, 0x088c, \ - 0x00000086, \ - "us", "en", \ -} - -/* Needs to be checked */ -#define CLIENTINFO_AIM_4_8_2540 { \ - "AOL Instant Messenger (SM), version 4.8.2540/WIN32", \ - 0x0109, \ - 0x0004, 0x0008, \ - 0x0000, 0x09ec, \ - 0x000000af, \ - "us", "en", \ -} - -/* Needs to be checked */ -#define CLIENTINFO_AIM_5_0_2938 { \ - "AOL Instant Messenger, version 5.0.2938/WIN32", \ - 0x0109, \ - 0x0005, 0x0000, \ - 0x0000, 0x0b7a, \ - 0x00000000, \ - "us", "en", \ -} - -#define CLIENTINFO_AIM_5_1_3036 { \ - "AOL Instant Messenger, version 5.1.3036/WIN32", \ - 0x0109, \ - 0x0005, 0x0001, \ - 0x0000, 0x0bdc, \ - 0x000000d2, \ - "us", "en", \ -} - -#define CLIENTINFO_AIM_5_5_3415 { \ - "AOL Instant Messenger, version 5.5.3415/WIN32", \ - 0x0109, \ - 0x0005, 0x0005, \ - 0x0000, 0x0057, \ - 0x000000ef, \ - "us", "en", \ -} - -#define CLIENTINFO_AIM_5_9_3702 { \ - "AOL Instant Messenger, version 5.9.3702/WIN32", \ - 0x0109, \ - 0x0005, 0x0009, \ - 0x0000, 0x0e76, \ - 0x00000111, \ - "us", "en", \ -} - -#define CLIENTINFO_ICHAT_1_0 { \ - "Apple iChat", \ - 0x311a, \ - 0x0001, 0x0000, \ - 0x0000, 0x003c, \ - 0x000000c6, \ - "us", "en", \ -} - -/* Needs to be checked */ -#define CLIENTINFO_ICQ_4_65_3281 { \ - "ICQ Inc. - Product of ICQ (TM) 2000b.4.65.1.3281.85", \ - 0x010a, \ - 0x0004, 0x0041, \ - 0x0001, 0x0cd1, \ - 0x00000055, \ - "us", "en", \ -} - -/* Needs to be checked */ -#define CLIENTINFO_ICQ_5_34_3728 { \ - "ICQ Inc. - Product of ICQ (TM).2002a.5.34.1.3728.85", \ - 0x010a, \ - 0x0005, 0x0022, \ - 0x0001, 0x0e8f, \ - 0x00000055, \ - "us", "en", \ -} - -#define CLIENTINFO_ICQ_5_45_3777 { \ - "ICQ Inc. - Product of ICQ (TM).2003a.5.45.1.3777.85", \ - 0x010a, \ - 0x0005, 0x002d, \ - 0x0001, 0x0ec1, \ - 0x00000055, \ - "us", "en", \ -} - -#define CLIENTINFO_ICQ6_6_0_6059 { \ - "ICQ Client", \ - 0x010a, \ - 0x0006, 0x0000, \ - 0x0000, 0x17ab, \ - 0x00007535, \ - "us", "en", \ -} - -#define CLIENTINFO_ICQBASIC_14_3_1068 { \ - "ICQBasic", \ - 0x010a, \ - 0x0014, 0x0003, \ - 0x0000, 0x042c, \ - 0x0000043d, \ - "us", "en", \ -} - -#define CLIENTINFO_ICQBASIC_14_34_3000 { \ - "ICQBasic", \ - 0x010a, \ - 0x0014, 0x0034, \ - 0x0000, 0x0bb8, \ - 0x0000043d, \ - "us", "en", \ -} - -#define CLIENTINFO_ICQBASIC_14_34_3096 { \ - "ICQBasic", \ - 0x010a, \ - 0x0014, 0x0034, \ - 0x0000, 0x0c18, \ - 0x0000043d, \ - "us", "en", \ -} - -#define CLIENTINFO_NETSCAPE_7_0_1 { \ - "Netscape 2000 an approved user of AOL Instant Messenger (SM)", \ - 0x1d0d, \ - 0x0007, 0x0000, \ - 0x0001, 0x0000, \ - 0x00000058, \ - "us", "en", \ -} - /* * We need to use the major-minor-micro versions from the official * AIM and ICQ programs here or AOL won't let us use certain features. @@ -329,9 +158,6 @@ "us", "en", \ } -#define CLIENTINFO_AIM_KNOWNGOOD CLIENTINFO_AIM_5_1_3036 -#define CLIENTINFO_ICQ_KNOWNGOOD CLIENTINFO_ICQBASIC_14_34_3096 - typedef enum { OSCAR_DISCONNECT_DONE, /* not considered an error */ @@ -596,10 +422,8 @@ #define AIM_ICQ_STATE_WEBAWARE 0x00010000 #define AIM_ICQ_STATE_HIDEIP 0x00020000 #define AIM_ICQ_STATE_BIRTHDAY 0x00080000 -#define AIM_ICQ_STATE_DIRECTDISABLED 0x00100000 #define AIM_ICQ_STATE_ICQHOMEPAGE 0x00200000 #define AIM_ICQ_STATE_DIRECTREQUIREAUTH 0x10000000 -#define AIM_ICQ_STATE_DIRECTCONTACTLIST 0x20000000 /** * Only used when connecting with the old-style BUCP login. @@ -698,64 +522,25 @@ void oscar_data_addhandler(OscarData *od, guint16 family, guint16 subtype, aim_rxcallback_t newhandler, guint16 flags); aim_rxcallback_t aim_callhandler(OscarData *od, guint16 family, guint16 subtype); -/* misc.c */ -#define AIM_VISIBILITYCHANGE_PERMITADD 0x05 -#define AIM_VISIBILITYCHANGE_PERMITREMOVE 0x06 -#define AIM_VISIBILITYCHANGE_DENYADD 0x07 -#define AIM_VISIBILITYCHANGE_DENYREMOVE 0x08 - -#define AIM_PRIVFLAGS_ALLOWIDLE 0x01 -#define AIM_PRIVFLAGS_ALLOWMEMBERSINCE 0x02 - -#define AIM_WARN_ANON 0x01 - - - /* 0x0001 - family_oservice.c */ /* 0x0002 */ void aim_srv_clientready(OscarData *od, FlapConnection *conn); /* 0x0004 */ void aim_srv_requestnew(OscarData *od, guint16 serviceid); /* 0x0006 */ void aim_srv_reqrates(OscarData *od, FlapConnection *conn); /* 0x0008 */ void aim_srv_rates_addparam(OscarData *od, FlapConnection *conn); -/* 0x0009 */ void aim_srv_rates_delparam(OscarData *od, FlapConnection *conn); -/* 0x000c */ void aim_srv_sendpauseack(OscarData *od, FlapConnection *conn); /* 0x000e */ void aim_srv_reqpersonalinfo(OscarData *od, FlapConnection *conn); /* 0x0011 */ void aim_srv_setidle(OscarData *od, guint32 idletime); -/* 0x0014 */ void aim_srv_setprivacyflags(OscarData *od, FlapConnection *conn, guint32); -/* 0x0016 */ void aim_srv_nop(OscarData *od, FlapConnection *conn); /* 0x0017 */ void aim_srv_setversions(OscarData *od, FlapConnection *conn); /* 0x001e */ int aim_srv_setextrainfo(OscarData *od, gboolean seticqstatus, guint32 icqstatus, gboolean setstatusmsg, const char *statusmsg, const char *itmsurl); void aim_bos_reqrights(OscarData *od, FlapConnection *conn); -int aim_bos_changevisibility(OscarData *od, FlapConnection *conn, int, const char *); -void aim_bos_setgroupperm(OscarData *od, FlapConnection *conn, guint32 mask); - - -#define AIM_CLIENTTYPE_UNKNOWN 0x0000 -#define AIM_CLIENTTYPE_MC 0x0001 -#define AIM_CLIENTTYPE_WINAIM 0x0002 -#define AIM_CLIENTTYPE_WINAIM41 0x0003 -#define AIM_CLIENTTYPE_AOL_TOC 0x0004 -guint16 aim_im_fingerprint(const guint8 *msghdr, int len); - -#define AIM_RATE_CODE_CHANGE 0x0001 -#define AIM_RATE_CODE_WARNING 0x0002 #define AIM_RATE_CODE_LIMIT 0x0003 -#define AIM_RATE_CODE_CLEARLIMIT 0x0004 -void aim_ads_requestads(OscarData *od, FlapConnection *conn); - - /* family_icbm.c */ -#define AIM_OFT_SUBTYPE_SEND_FILE 0x0001 #define AIM_OFT_SUBTYPE_SEND_DIR 0x0002 -#define AIM_OFT_SUBTYPE_GET_FILE 0x0011 -#define AIM_OFT_SUBTYPE_GET_LIST 0x0012 -#define AIM_TRANSFER_DENY_NOTSUPPORTED 0x0000 #define AIM_TRANSFER_DENY_DECLINE 0x0001 -#define AIM_TRANSFER_DENY_NOTACCEPTING 0x0002 #define AIM_IMPARAM_FLAG_CHANNEL_MSGS_ALLOWED 0x00000001 #define AIM_IMPARAM_FLAG_MISSED_CALLS_ENABLED 0x00000002 @@ -777,26 +562,6 @@ */ #define AIM_IMPARAM_FLAG_USE_HTML_FOR_ICQ 0x00000400 -/* This is what the server will give you if you don't set them yourself. */ -/* This is probably out of date. */ -#define AIM_IMPARAM_DEFAULTS { \ - 0, \ - AIM_IMPARAM_FLAG_CHANNEL_MSGS_ALLOWED | AIM_IMPARAM_FLAG_MISSED_CALLS_ENABLED, \ - 512, /* !! Note how small this is. */ \ - (99.9)*10, (99.9)*10, \ - 1000 /* !! And how large this is. */ \ -} - -/* This is what most AIM versions use. */ -/* This is probably out of date. */ -#define AIM_IMPARAM_REASONABLE { \ - 0, \ - AIM_IMPARAM_FLAG_CHANNEL_MSGS_ALLOWED | AIM_IMPARAM_FLAG_MISSED_CALLS_ENABLED, \ - 8000, \ - (99.9)*10, (99.9)*10, \ - 0 \ -} - struct aim_icbmparameters { guint16 maxchan; @@ -843,9 +608,6 @@ #define AIM_IMFLAGS_HASICON 0x0020 /* already has icon */ #define AIM_IMFLAGS_SUBENC_MACINTOSH 0x0040 /* damn that Steve Jobs! */ #define AIM_IMFLAGS_CUSTOMFEATURES 0x0080 /* features field present */ -#define AIM_IMFLAGS_EXTDATA 0x0100 -#define AIM_IMFLAGS_X 0x0200 -#define AIM_IMFLAGS_MULTIPART 0x0400 /* ->mpmsg section valid */ #define AIM_IMFLAGS_OFFLINE 0x0800 /* send to offline user */ #define AIM_IMFLAGS_TYPINGNOT 0x1000 /* typing notification */ @@ -854,30 +616,6 @@ #define AIM_CHARSET_LATIN_1 0x0003 /* ISO 8859-1 */ /* - * Multipart message structures. - */ -typedef struct aim_mpmsg_section_s -{ - guint16 charset; - guint16 charsubset; - gchar *data; - guint16 datalen; - struct aim_mpmsg_section_s *next; -} aim_mpmsg_section_t; - -typedef struct aim_mpmsg_s -{ - unsigned int numparts; - aim_mpmsg_section_t *parts; -} aim_mpmsg_t; - -int aim_mpmsg_init(OscarData *od, aim_mpmsg_t *mpm); -int aim_mpmsg_addraw(OscarData *od, aim_mpmsg_t *mpm, guint16 charset, guint16 charsubset, const gchar *data, guint16 datalen); -int aim_mpmsg_addascii(OscarData *od, aim_mpmsg_t *mpm, const char *ascii); -int aim_mpmsg_addunicode(OscarData *od, aim_mpmsg_t *mpm, const guint16 *unicode, guint16 unicodelen); -void aim_mpmsg_free(OscarData *od, aim_mpmsg_t *mpm); - -/* * Arguments to aim_send_im_ext(). * * This is really complicated. But immensely versatile. @@ -885,84 +623,39 @@ */ struct aim_sendimext_args { - /* These are _required_ */ const char *destbn; guint32 flags; /* often 0 */ - /* Only required if not using multipart messages */ const char *msg; - int msglen; - - /* Required if ->msg is not provided */ - aim_mpmsg_t *mpmsg; + gsize msglen; /* Only used if AIM_IMFLAGS_HASICON is set */ guint32 iconlen; time_t iconstamp; guint32 iconsum; - /* Only used if AIM_IMFLAGS_CUSTOMFEATURES is set */ guint16 featureslen; guint8 *features; - /* Only used if AIM_IMFLAGS_CUSTOMCHARSET is set and mpmsg not used */ guint16 charset; - guint16 charsubset; -}; - -/* - * Arguments to aim_send_rtfmsg(). - */ -struct aim_sendrtfmsg_args -{ - const char *destbn; - guint32 fgcolor; - guint32 bgcolor; - const char *rtfmsg; /* must be in RTF */ }; /* * This information is provided in the Incoming ICBM callback for * Channel 1 ICBM's. - * - * Note that although CUSTOMFEATURES and CUSTOMCHARSET say they - * are optional, both are always set by the current libfaim code. - * That may or may not change in the future. It is mainly for - * consistency with aim_sendimext_args. - * - * Multipart messages require some explanation. If you want to use them, - * I suggest you read all the comments in family_icbm.c. - * */ struct aim_incomingim_ch1_args { - - /* Always provided */ - aim_mpmsg_t mpmsg; guint32 icbmflags; /* some flags apply only to ->msg, not all mpmsg */ time_t timestamp; /* Only set for offline messages */ - /* Only provided if message has a human-readable section */ gchar *msg; - int msglen; /* Only provided if AIM_IMFLAGS_HASICON is set */ time_t iconstamp; guint32 iconlen; guint16 iconsum; - - /* Only provided if AIM_IMFLAGS_CUSTOMFEATURES is set */ - guint8 *features; - guint8 featureslen; - - /* Only provided if AIM_IMFLAGS_EXTDATA is set */ - guint8 extdatalen; - guint8 *extdata; - - /* Only used if AIM_IMFLAGS_CUSTOMCHARSET is set */ - guint16 charset; - guint16 charsubset; }; /* Valid values for channel 2 args->status */ @@ -997,10 +690,8 @@ struct aim_chat_roominfo roominfo; } chat; struct { - guint16 msgtype; - guint32 fgcolor; - guint32 bgcolor; - const char *rtfmsg; + guint8 msgtype; + const char *msg; } rtfmsg; struct { guint16 subtype; @@ -1012,11 +703,6 @@ void *destructor; /* used internally only */ }; -/* Valid values for channel 4 args->type */ -#define AIM_ICQMSG_AUTHREQUEST 0x0006 -#define AIM_ICQMSG_AUTHDENIED 0x0007 -#define AIM_ICQMSG_AUTHGRANTED 0x0008 - struct aim_incomingim_ch4_args { guint32 uin; /* Of the sender of the ICBM */ @@ -1033,7 +719,6 @@ /* 0x0006 */ int aim_im_sendch1(OscarData *, const char *destbn, guint16 flags, const char *msg); /* 0x0006 */ int aim_im_sendch2_chatinvite(OscarData *od, const char *bn, const char *msg, guint16 exchange, const char *roomname, guint16 instance); /* 0x0006 */ int aim_im_sendch2_icon(OscarData *od, const char *bn, const guint8 *icon, int iconlen, time_t stamp, guint16 iconsum); -/* 0x0006 */ int aim_im_sendch2_rtfmsg(OscarData *od, struct aim_sendrtfmsg_args *args); /* 0x0006 */ void aim_im_sendch2_cancel(PeerConnection *peer_conn); /* 0x0006 */ void aim_im_sendch2_connected(PeerConnection *peer_conn); @@ -1042,39 +727,22 @@ /* 0x0006 */ void aim_im_sendch2_sendfile_requestdirect(OscarData *od, guchar *cookie, const char *bn, const guint8 *ip, guint16 port, guint16 requestnumber, const gchar *filename, guint32 size, guint16 numfiles); /* 0x0006 */ void aim_im_sendch2_sendfile_requestproxy(OscarData *od, guchar *cookie, const char *bn, const guint8 *ip, guint16 pin, guint16 requestnumber, const gchar *filename, guint32 size, guint16 numfiles); -/* 0x0006 */ int aim_im_sendch2_geticqaway(OscarData *od, const char *bn, int type); -/* 0x0006 */ int aim_im_sendch4(OscarData *od, const char *bn, guint16 type, const char *message); -/* 0x0008 */ int aim_im_warn(OscarData *od, FlapConnection *conn, const char *destbn, guint32 flags); /* 0x000b */ int aim_im_denytransfer(OscarData *od, const char *bn, const guchar *cookie, guint16 code); /* 0x0010 */ int aim_im_reqofflinemsgs(OscarData *od); /* 0x0014 */ int aim_im_sendmtn(OscarData *od, guint16 type1, const char *bn, guint16 type2); /* 0x000b */ int icq_relay_xstatus (OscarData *od, const char *sn, const guchar* cookie); void aim_icbm_makecookie(guchar* cookie); -gchar *oscar_encoding_extract(const char *encoding); -gchar *oscar_encoding_to_utf8(PurpleAccount *account, const char *encoding, const char *text, int textlen); -gchar *oscar_utf8_try_convert(PurpleAccount *account, OscarData *od, const gchar *msg); -gchar *purple_plugin_oscar_decode_im_part(PurpleAccount *account, const char *sourcebn, guint16 charset, guint16 charsubset, const gchar *data, gsize datalen); - /* 0x0002 - family_locate.c */ /* * AIM User Info, Standard Form. */ -#define AIM_FLAG_UNCONFIRMED 0x0001 /* "damned transients" */ #define AIM_FLAG_ADMINISTRATOR 0x0002 #define AIM_FLAG_AOL 0x0004 -#define AIM_FLAG_OSCAR_PAY 0x0008 -#define AIM_FLAG_FREE 0x0010 #define AIM_FLAG_AWAY 0x0020 -#define AIM_FLAG_ICQ 0x0040 #define AIM_FLAG_WIRELESS 0x0080 -#define AIM_FLAG_UNKNOWN100 0x0100 -#define AIM_FLAG_IMFORWARDING 0x0200 +#define AIM_FLAG_ICQ 0x0040 #define AIM_FLAG_ACTIVEBUDDY 0x0400 -#define AIM_FLAG_UNKNOWN800 0x0800 -#define AIM_FLAG_ONEWAYWIRELESS 0x1000 -#define AIM_FLAG_NOKNOCKKNOCK 0x00040000 -#define AIM_FLAG_FORWARD_MOBILE 0x00080000 #define AIM_USERINFO_PRESENT_FLAGS 0x00000001 #define AIM_USERINFO_PRESENT_MEMBERSINCE 0x00000002 @@ -1147,22 +815,8 @@ guint16 instance; }; -#define AIM_COOKIETYPE_UNKNOWN 0x00 -#define AIM_COOKIETYPE_ICBM 0x01 -#define AIM_COOKIETYPE_ADS 0x02 -#define AIM_COOKIETYPE_BOS 0x03 -#define AIM_COOKIETYPE_IM 0x04 -#define AIM_COOKIETYPE_CHAT 0x05 -#define AIM_COOKIETYPE_CHATNAV 0x06 -#define AIM_COOKIETYPE_INVITE 0x07 -/* we'll move OFT up a bit to give breathing room. not like it really - * matters. */ -#define AIM_COOKIETYPE_OFTIM 0x10 -#define AIM_COOKIETYPE_OFTGET 0x11 -#define AIM_COOKIETYPE_OFTSEND 0x12 -#define AIM_COOKIETYPE_OFTVOICE 0x13 -#define AIM_COOKIETYPE_OFTIMAGE 0x14 -#define AIM_COOKIETYPE_OFTICON 0x15 +#define AIM_COOKIETYPE_CHAT 0x01 +#define AIM_COOKIETYPE_INVITE 0x02 aim_userinfo_t *aim_locate_finduserinfo(OscarData *od, const char *bn); void aim_locate_dorequest(OscarData *od); @@ -1170,10 +824,6 @@ /* 0x0002 */ int aim_locate_reqrights(OscarData *od); /* 0x0004 */ int aim_locate_setcaps(OscarData *od, guint64 caps); /* 0x0004 */ int aim_locate_setprofile(OscarData *od, const char *profile_encoding, const gchar *profile, const int profile_len, const char *awaymsg_encoding, const gchar *awaymsg, const int awaymsg_len); -/* 0x0005 */ int aim_locate_getinfo(OscarData *od, const char *, guint16); -/* 0x0009 */ int aim_locate_setdirinfo(OscarData *od, const char *first, const char *middle, const char *last, const char *maiden, const char *nickname, const char *street, const char *city, const char *state, const char *zip, int country, guint16 privacy); -/* 0x000b */ int aim_locate_000b(OscarData *od, const char *bn); -/* 0x000f */ int aim_locate_setinterests(OscarData *od, const char *interest1, const char *interest2, const char *interest3, const char *interest4, const char *interest5, guint16 privacy); /* 0x0015 */ int aim_locate_getinfoshort(OscarData *od, const char *bn, guint32 flags); guint64 aim_locate_getcaps(OscarData *od, ByteStream *bs, int len); @@ -1188,25 +838,11 @@ /* 0x0003 - family_buddy.c */ /* 0x0002 */ void aim_buddylist_reqrights(OscarData *, FlapConnection *); -/* 0x0004 */ int aim_buddylist_set(OscarData *, FlapConnection *, const char *); -/* 0x0004 */ int aim_buddylist_addbuddy(OscarData *, FlapConnection *, const char *); -/* 0x0005 */ int aim_buddylist_removebuddy(OscarData *, FlapConnection *, const char *); - /* 0x000a - family_userlookup.c */ int aim_search_address(OscarData *, const char *); - - -/* 0x000d - family_chatnav.c */ -/* 0x000e - family_chat.c */ -/* These apply to exchanges as well. */ -#define AIM_CHATROOM_FLAG_EVILABLE 0x0001 -#define AIM_CHATROOM_FLAG_NAV_ONLY 0x0002 -#define AIM_CHATROOM_FLAG_INSTANCING_ALLOWED 0x0004 -#define AIM_CHATROOM_FLAG_OCCUPANT_PEEK_ALLOWED 0x0008 - struct aim_chat_exchangeinfo { guint16 number; @@ -1222,41 +858,10 @@ #define AIM_CHATFLAGS_AWAY 0x0002 int aim_chat_send_im(OscarData *od, FlapConnection *conn, guint16 flags, const gchar *msg, int msglen, const char *encoding, const char *language); int aim_chat_join(OscarData *od, guint16 exchange, const char *roomname, guint16 instance); -int aim_chat_attachname(FlapConnection *conn, guint16 exchange, const char *roomname, guint16 instance); -char *aim_chat_getname(FlapConnection *conn); -FlapConnection *aim_chat_getconn(OscarData *, const char *name); void aim_chatnav_reqrights(OscarData *od, FlapConnection *conn); int aim_chatnav_createroom(OscarData *od, FlapConnection *conn, const char *name, guint16 exchange); -int aim_chat_leaveroom(OscarData *od, const char *name); - - - -/* 0x000f - family_odir.c */ -struct aim_odir -{ - char *first; - char *last; - char *middle; - char *maiden; - char *email; - char *country; - char *state; - char *city; - char *bn; - char *interest; - char *nick; - char *zip; - char *region; - char *address; - struct aim_odir *next; -}; - -int aim_odir_email(OscarData *, const char *, const char *); -int aim_odir_name(OscarData *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *); -int aim_odir_interest(OscarData *, const char *, const char *); - /* 0x0010 - family_bart.c */ @@ -1275,13 +880,6 @@ #define AIM_SSI_TYPE_ICQDENY 0x000e #define AIM_SSI_TYPE_ICONINFO 0x0014 -#define AIM_SSI_ACK_SUCCESS 0x0000 -#define AIM_SSI_ACK_ITEMNOTFOUND 0x0002 -#define AIM_SSI_ACK_IDNUMINUSE 0x000a -#define AIM_SSI_ACK_ATMAX 0x000c -#define AIM_SSI_ACK_INVALIDNAME 0x000d -#define AIM_SSI_ACK_AUTHREQUIRED 0x000e - /* These flags are set in the 0x00c9 TLV of SSI type 0x0005 */ #define AIM_SSI_PRESENCE_FLAG_SHOWIDLE 0x00000400 #define AIM_SSI_PRESENCE_FLAG_NORECENTBUDDIES 0x00020000 @@ -1308,11 +906,9 @@ /* These build the actual SNACs and queue them to be sent */ /* 0x0002 */ int aim_ssi_reqrights(OscarData *od); /* 0x0004 */ int aim_ssi_reqdata(OscarData *od); -/* 0x0005 */ int aim_ssi_reqifchanged(OscarData *od, time_t localstamp, guint16 localrev); /* 0x0007 */ int aim_ssi_enable(OscarData *od); /* 0x0011 */ int aim_ssi_modbegin(OscarData *od); /* 0x0012 */ int aim_ssi_modend(OscarData *od); -/* 0x0014 */ int aim_ssi_sendauth(OscarData *od, char *bn, char *msg); /* 0x0018 */ int aim_ssi_sendauthrequest(OscarData *od, char *bn, const char *msg); /* 0x001a */ int aim_ssi_sendauthreply(OscarData *od, char *bn, guint8 reply, const char *msg); @@ -1346,18 +942,6 @@ guint16 aim_ssi_getdenyentrytype(OscarData* od); -/* 0x0015 - family_icq.c */ -#define AIM_ICQ_INFO_SIMPLE 0x001 -#define AIM_ICQ_INFO_SUMMARY 0x002 -#define AIM_ICQ_INFO_EMAIL 0x004 -#define AIM_ICQ_INFO_PERSONAL 0x008 -#define AIM_ICQ_INFO_ADDITIONAL 0x010 -#define AIM_ICQ_INFO_WORK 0x020 -#define AIM_ICQ_INFO_INTERESTS 0x040 -#define AIM_ICQ_INFO_ORGS 0x080 -#define AIM_ICQ_INFO_UNKNOWN 0x100 -#define AIM_ICQ_INFO_HAVEALL 0x1ff - struct aim_icq_info { guint16 reqid; @@ -1563,9 +1147,6 @@ gchar *oscar_get_clientstring(void); guint16 aimutil_iconsum(const guint8 *buf, int buflen); -int aimutil_tokslen(char *toSearch, int theindex, char dl); -int aimutil_itemcnt(char *toSearch, char dl); -char *aimutil_itemindex(char *toSearch, int theindex, char dl); gboolean oscar_util_valid_name(const char *bn); gboolean oscar_util_valid_name_icq(const char *bn); @@ -1614,11 +1195,7 @@ int chat_modfirst(OscarData *od, aim_module_t *mod); int locate_modfirst(OscarData *od, aim_module_t *mod); int service_modfirst(OscarData *od, aim_module_t *mod); -int invite_modfirst(OscarData *od, aim_module_t *mod); -int translate_modfirst(OscarData *od, aim_module_t *mod); int popups_modfirst(OscarData *od, aim_module_t *mod); -int adverts_modfirst(OscarData *od, aim_module_t *mod); -int odir_modfirst(OscarData *od, aim_module_t *mod); int bart_modfirst(OscarData *od, aim_module_t *mod); int ssi_modfirst(OscarData *od, aim_module_t *mod); int icq_modfirst(OscarData *od, aim_module_t *mod); @@ -1627,13 +1204,12 @@ void aim_genericreq_n(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype); void aim_genericreq_n_snacid(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype); void aim_genericreq_l(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype, guint32 *); -void aim_genericreq_s(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype, guint16 *); /* bstream.c */ int byte_stream_new(ByteStream *bs, guint32 len); int byte_stream_init(ByteStream *bs, guint8 *data, int len); void byte_stream_destroy(ByteStream *bs); -int byte_stream_empty(ByteStream *bs); +int byte_stream_bytes_left(ByteStream *bs); int byte_stream_curpos(ByteStream *bs); int byte_stream_setpos(ByteStream *bs, unsigned int off); void byte_stream_rewind(ByteStream *bs); @@ -1717,7 +1293,6 @@ IcbmCookie *aim_mkcookie(guint8 *, int, void *); IcbmCookie *aim_checkcookie(OscarData *, const unsigned char *, const int); int aim_freecookie(OscarData *od, IcbmCookie *cookie); -int aim_msgcookie_gettype(guint64 type); int aim_cookie_free(OscarData *od, IcbmCookie *cookie); int aim_chat_readroominfo(ByteStream *bs, struct aim_chat_roominfo *outinfo);
--- a/libpurple/protocols/oscar/oscar_data.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/oscar_data.c Thu Jul 29 00:06:56 2010 +0000 @@ -53,17 +53,13 @@ aim__registermodule(od, locate_modfirst); aim__registermodule(od, buddylist_modfirst); aim__registermodule(od, msg_modfirst); - /* aim__registermodule(od, adverts_modfirst); */ - /* aim__registermodule(od, invite_modfirst); */ aim__registermodule(od, admin_modfirst); aim__registermodule(od, popups_modfirst); aim__registermodule(od, bos_modfirst); aim__registermodule(od, search_modfirst); aim__registermodule(od, stats_modfirst); - /* aim__registermodule(od, translate_modfirst); */ aim__registermodule(od, chatnav_modfirst); aim__registermodule(od, chat_modfirst); - aim__registermodule(od, odir_modfirst); aim__registermodule(od, bart_modfirst); /* missing 0x11 - 0x12 */ aim__registermodule(od, ssi_modfirst);
--- a/libpurple/protocols/oscar/peer_proxy.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/peer_proxy.c Thu Jul 29 00:06:56 2010 +0000 @@ -168,7 +168,7 @@ } else if (frame->type == PEER_PROXY_TYPE_ERROR) { - if (byte_stream_empty(&frame->payload) >= 2) + if (byte_stream_bytes_left(&frame->payload) >= 2) { guint16 error; const char *msg;
--- a/libpurple/protocols/oscar/rxhandlers.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/rxhandlers.c Thu Jul 29 00:06:56 2010 +0000 @@ -95,194 +95,3 @@ return; } - -#if 0 -/* - * Bleck functions get called when there's no non-bleck functions - * around to cleanup the mess... - */ -static int bleck(OscarData *od, FlapFrame *frame, ...) -{ - guint16 family, subtype; - guint16 maxf, maxs; - - static const char *channels[6] = { - "Invalid (0)", - "FLAP Version", - "SNAC", - "Invalid (3)", - "Negotiation", - "FLAP NOP" - }; - static const int maxchannels = 5; - - /* XXX: this is ugly. and big just for debugging. */ - static const char *literals[14][25] = { - {"Invalid", - NULL - }, - {"General", - "Invalid", - "Error", - "Client Ready", - "Server Ready", - "Service Request", - "Redirect", - "Rate Information Request", - "Rate Information", - "Rate Information Ack", - NULL, - "Rate Information Change", - "Server Pause", - NULL, - "Server Resume", - "Request Personal User Information", - "Personal User Information", - "Evil Notification", - NULL, - "Migration notice", - "Message of the Day", - "Set Privacy Flags", - "Well Known URL", - "NOP" - }, - {"Location", - "Invalid", - "Error", - "Request Rights", - "Rights Information", - "Set user information", - "Request User Information", - "User Information", - "Watcher Sub Request", - "Watcher Notification" - }, - {"Buddy List Management", - "Invalid", - "Error", - "Request Rights", - "Rights Information", - "Add Buddy", - "Remove Buddy", - "Watcher List Query", - "Watcher List Response", - "Watcher SubRequest", - "Watcher Notification", - "Reject Notification", - "Oncoming Buddy", - "Offgoing Buddy" - }, - {"Messeging", - "Invalid", - "Error", - "Add ICBM Parameter", - "Remove ICBM Parameter", - "Request Parameter Information", - "Parameter Information", - "Outgoing Message", - "Incoming Message", - "Evil Request", - "Evil Reply", - "Missed Calls", - "Message Error", - "Host Ack" - }, - {"Advertisements", - "Invalid", - "Error", - "Request Ad", - "Ad Data (GIFs)" - }, - {"Invitation / Client-to-Client", - "Invalid", - "Error", - "Invite a Friend", - "Invitation Ack" - }, - {"Administrative", - "Invalid", - "Error", - "Information Request", - "Information Reply", - "Information Change Request", - "Information Chat Reply", - "Account Confirm Request", - "Account Confirm Reply", - "Account Delete Request", - "Account Delete Reply" - }, - {"Popups", - "Invalid", - "Error", - "Display Popup" - }, - {"BOS", - "Invalid", - "Error", - "Request Rights", - "Rights Response", - "Set group permission mask", - "Add permission list entries", - "Delete permission list entries", - "Add deny list entries", - "Delete deny list entries", - "Server Error" - }, - {"User Lookup", - "Invalid", - "Error", - "Search Request", - "Search Response" - }, - {"Stats", - "Invalid", - "Error", - "Set minimum report interval", - "Report Events" - }, - {"Translate", - "Invalid", - "Error", - "Translate Request", - "Translate Reply", - }, - {"Chat Navigation", - "Invalid", - "Error", - "Request rights", - "Request Exchange Information", - "Request Room Information", - "Request Occupant List", - "Search for Room", - "Outgoing Message", - "Incoming Message", - "Evil Request", - "Evil Reply", - "Chat Error", - } - }; - - maxf = sizeof(literals) / sizeof(literals[0]); - maxs = sizeof(literals[0]) / sizeof(literals[0][0]); - - if (frame->channel == 0x02) { - - family = byte_stream_get16(&frame->data); - subtype = byte_stream_get16(&frame->data); - - if ((family < maxf) && (subtype+1 < maxs) && (literals[family][subtype] != NULL)) - purple_debug_misc("oscar", "bleck: channel %s: null handler for %04x/%04x (%s)\n", channels[frame->channel], family, subtype, literals[family][subtype+1]); - else - purple_debug_misc("oscar", "bleck: channel %s: null handler for %04x/%04x (no literal)\n", channels[frame->channel], family, subtype); - } else { - - if (frame->channel <= maxchannels) - purple_debug_misc("oscar", "bleck: channel %s (0x%02x)\n", channels[frame->channel], frame->channel); - else - purple_debug_misc("oscar", "bleck: unknown channel 0x%02x\n", frame->channel); - - } - - return 1; -} -#endif
--- a/libpurple/protocols/oscar/tlv.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/tlv.c Thu Jul 29 00:06:56 2010 +0000 @@ -49,27 +49,7 @@ type = byte_stream_get16(bs); length = byte_stream_get16(bs); -#if 0 - /* - * This code hasn't been needed in years. It's been commented - * out since 2003, at the latest. It seems likely that it was - * just a bug in their server code that has since been fixed. - * In any case, here's the orignal comment, kept for historical - * purposes: - * - * Okay, so now AOL has decided that any TLV of - * type 0x0013 can only be two bytes, despite - * what the actual given length is. So here - * we dump any invalid TLVs of that sort. Hopefully - * there's no special cases to this special case. - * - mid (30jun2000) - */ - if ((type == 0x0013) && (length != 0x0002)) { - length = 0x0002; - return list; - } -#endif - if (length > byte_stream_empty(bs)) { + if (length > byte_stream_bytes_left(bs)) { aim_tlvlist_free(list); return NULL; } @@ -108,7 +88,7 @@ { GSList *list = NULL; - while (byte_stream_empty(bs) > 0) { + while (byte_stream_bytes_left(bs) > 0) { list = aim_tlv_read(list, bs); if (list == NULL) return NULL; @@ -142,7 +122,7 @@ { GSList *list = NULL; - while ((byte_stream_empty(bs) > 0) && (num != 0)) { + while ((byte_stream_bytes_left(bs) > 0) && (num != 0)) { list = aim_tlv_read(list, bs); if (list == NULL) return NULL; @@ -177,7 +157,7 @@ { GSList *list = NULL; - while ((byte_stream_empty(bs) > 0) && (len > 0)) { + while ((byte_stream_bytes_left(bs) > 0) && (len > 0)) { list = aim_tlv_read(list, bs); if (list == NULL) return NULL; @@ -668,7 +648,7 @@ /* do an initial run to test total length */ goodbuflen = aim_tlvlist_size(*list); - if (goodbuflen > byte_stream_empty(bs)) + if (goodbuflen > byte_stream_bytes_left(bs)) return 0; /* not enough buffer */ /* do the real write-out */
--- a/libpurple/protocols/oscar/userinfo.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/userinfo.c Thu Jul 29 00:06:56 2010 +0000 @@ -22,6 +22,7 @@ * Displaying various information about buddies. */ +#include "encoding.h" #include "oscar.h" static gchar * @@ -190,30 +191,21 @@ the "message" attribute of the status contains only the plaintext message. */ if (userinfo) { - if ((userinfo->flags & AIM_FLAG_AWAY) - && userinfo->away_len > 0 - && userinfo->away != NULL - && userinfo->away_encoding != NULL) - { + if ((userinfo->flags & AIM_FLAG_AWAY) && userinfo->away_len > 0 && userinfo->away != NULL && userinfo->away_encoding != NULL) { /* Away message */ - tmp = oscar_encoding_extract(userinfo->away_encoding); - message = oscar_encoding_to_utf8(account, - tmp, userinfo->away, userinfo->away_len); - g_free(tmp); + message = oscar_encoding_to_utf8(userinfo->away_encoding, userinfo->away, userinfo->away_len); } else { /* * Available message or non-HTML away message (because that's * all we have right now. */ if ((userinfo->status != NULL) && userinfo->status[0] != '\0') { - message = oscar_encoding_to_utf8(account, - userinfo->status_encoding, userinfo->status, - userinfo->status_len); + message = oscar_encoding_to_utf8(userinfo->status_encoding, userinfo->status, userinfo->status_len); } #if defined (_WIN32) || defined (__APPLE__) - if (userinfo->itmsurl && (userinfo->itmsurl[0] != '\0')) - itmsurl = oscar_encoding_to_utf8(account, userinfo->itmsurl_encoding, - userinfo->itmsurl, userinfo->itmsurl_len); + if (userinfo->itmsurl && (userinfo->itmsurl[0] != '\0')) { + itmsurl = oscar_encoding_to_utf8(userinfo->itmsurl_encoding, userinfo->itmsurl, userinfo->itmsurl_len); + } #endif } } else { @@ -551,17 +543,12 @@ /* Info */ if ((userinfo->info_len > 0) && (userinfo->info != NULL) && (userinfo->info_encoding != NULL)) { - tmp = oscar_encoding_extract(userinfo->info_encoding); - info_utf8 = oscar_encoding_to_utf8(account, tmp, userinfo->info, - userinfo->info_len); + info_utf8 = oscar_encoding_to_utf8(userinfo->info_encoding, userinfo->info, userinfo->info_len); + tmp = oscar_util_format_string(info_utf8, purple_account_get_username(account)); + purple_notify_user_info_add_section_break(user_info); + oscar_user_info_add_pair(user_info, _("Profile"), tmp); g_free(tmp); - if (info_utf8 != NULL) { - tmp = oscar_util_format_string(info_utf8, purple_account_get_username(account)); - purple_notify_user_info_add_section_break(user_info); - oscar_user_info_add_pair(user_info, _("Profile"), tmp); - g_free(tmp); - g_free(info_utf8); - } + g_free(info_utf8); } purple_notify_user_info_add_section_break(user_info);
--- a/libpurple/protocols/oscar/util.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/util.c Thu Jul 29 00:06:56 2010 +0000 @@ -107,91 +107,6 @@ return g_strdup_printf("%s/%s", name, version);; } -/* - * Tokenizing functions. Used to portably replace strtok/sep. - * -- DMP. - * - */ -/* TODO: Get rid of this and use glib functions */ -int -aimutil_tokslen(char *toSearch, int theindex, char dl) -{ - int curCount = 1; - char *next; - char *last; - int toReturn; - - last = toSearch; - next = strchr(toSearch, dl); - - while(curCount < theindex && next != NULL) { - curCount++; - last = next + 1; - next = strchr(last, dl); - } - - if ((curCount < theindex) || (next == NULL)) - toReturn = strlen(toSearch) - (curCount - 1); - else - toReturn = next - toSearch - (curCount - 1); - - return toReturn; -} - -int -aimutil_itemcnt(char *toSearch, char dl) -{ - int curCount; - char *next; - - curCount = 1; - - next = strchr(toSearch, dl); - - while(next != NULL) { - curCount++; - next = strchr(next + 1, dl); - } - - return curCount; -} - -char * -aimutil_itemindex(char *toSearch, int theindex, char dl) -{ - int curCount; - char *next; - char *last; - char *toReturn; - - curCount = 0; - - last = toSearch; - next = strchr(toSearch, dl); - - while (curCount < theindex && next != NULL) { - curCount++; - last = next + 1; - next = strchr(last, dl); - } - next = strchr(last, dl); - - if (curCount < theindex) { - toReturn = g_malloc(sizeof(char)); - *toReturn = '\0'; - } else { - if (next == NULL) { - toReturn = g_malloc((strlen(last) + 1) * sizeof(char)); - strcpy(toReturn, last); - } else { - toReturn = g_malloc((next - last + 1) * sizeof(char)); - memcpy(toReturn, last, (next - last)); - toReturn[next - last] = '\0'; - } - } - return toReturn; -} - /** * Calculate the checksum of a given icon. */ @@ -392,22 +307,20 @@ oscar_format_buddies(GSList *buddies, const gchar *no_buddies_message) { GSList *cur; - gchar *result, *tmp; + GString *result; if (!buddies) { return g_strdup_printf("<i>%s</i>", no_buddies_message); } - result = g_strdup(""); + result = g_string_new(""); for (cur = buddies; cur != NULL; cur = cur->next) { PurpleBuddy *buddy = cur->data; const gchar *bname = purple_buddy_get_name(buddy); const gchar *alias = purple_buddy_get_alias_only(buddy); + g_string_append(result, bname); if (alias) { - tmp = g_strdup_printf("%s%s (%s)<br>", result, bname, alias); - } else { - tmp = g_strdup_printf("%s%s<br>", result, bname); + g_string_append_printf(result, " (%s)", alias); } - g_free(result); - result = tmp; + g_string_append(result, "<br>"); } - return result; + return g_string_free(result, FALSE); } \ No newline at end of file
--- a/libpurple/protocols/oscar/visibility.c Thu Jul 08 17:00:45 2010 +0000 +++ b/libpurple/protocols/oscar/visibility.c Thu Jul 29 00:06:56 2010 +0000 @@ -27,7 +27,7 @@ #define DONT_APPEAR_OFFLINE N_("Don't Appear Offline") static guint16 -get_buddy_list_type(OscarData *od, const char *bname) +get_buddy_list_type(OscarData *od) { PurpleAccount *account = purple_connection_get_account(od->gc); return purple_account_is_status_active(account, OSCAR_STATUS_ID_INVISIBLE) ? AIM_SSI_TYPE_PERMIT : AIM_SSI_TYPE_DENY; @@ -36,7 +36,7 @@ static gboolean is_buddy_on_list(OscarData *od, const char *bname) { - return aim_ssi_itemlist_finditem(od->ssi.local, NULL, bname, get_buddy_list_type(od, bname)) != NULL; + return aim_ssi_itemlist_finditem(od->ssi.local, NULL, bname, get_buddy_list_type(od)) != NULL; } static void @@ -45,7 +45,7 @@ PurpleBuddy *buddy = PURPLE_BUDDY(node); const char* bname = purple_buddy_get_name(buddy); OscarData *od = purple_connection_get_protocol_data(purple_account_get_connection(purple_buddy_get_account(buddy))); - guint16 list_type = get_buddy_list_type(od, bname); + guint16 list_type = get_buddy_list_type(od); if (!is_buddy_on_list(od, bname)) { aim_ssi_add_to_private_list(od, bname, list_type); @@ -71,7 +71,7 @@ } static void -show_private_list(PurplePluginAction *action, guint16 list_type, const gchar *list_description, const gchar *menu_action_name) +show_private_list(PurplePluginAction *action, guint16 list_type, const gchar *title, const gchar *list_description, const gchar *menu_action_name) { PurpleConnection *gc = (PurpleConnection *) action->context; OscarData *od = purple_connection_get_protocol_data(gc); @@ -101,7 +101,7 @@ secondary = g_strdup_printf(_("You can add a buddy to this list " "by right-clicking on them and " "selecting \"%s\""), menu_action_name); - purple_notify_formatted(gc, NULL, list_description, secondary, text, NULL, NULL); + purple_notify_formatted(gc, title, list_description, secondary, text, NULL, NULL); g_free(secondary); g_free(text); } @@ -109,7 +109,8 @@ void oscar_show_visible_list(PurplePluginAction *action) { - show_private_list(action, AIM_SSI_TYPE_PERMIT, _("These buddies will see " + show_private_list(action, AIM_SSI_TYPE_PERMIT, _("Visible List"), + _("These buddies will see " "your status when you switch " "to \"Invisible\""), _(APPEAR_ONLINE)); @@ -118,5 +119,7 @@ void oscar_show_invisible_list(PurplePluginAction *action) { - show_private_list(action, AIM_SSI_TYPE_DENY, _("These buddies will always see you as offline"), _(APPEAR_OFFLINE)); + show_private_list(action, AIM_SSI_TYPE_DENY, _("Invisible List"), + _("These buddies will always see you as offline"), + _(APPEAR_OFFLINE)); } \ No newline at end of file