| 1 /* |
|
| 2 * gaim |
|
| 3 * |
|
| 4 * Some code copyright (C) 1998-1999, Mark Spencer <markster@marko.net> |
|
| 5 * Some code copyright (C) 1999-2001, Eric Warmenhoven |
|
| 6 * Some code copyright (C) 2001-2003, Sean Egan |
|
| 7 * Some code copyright (C) 2001-2005, Mark Doliner <thekingant@users.sourceforge.net> |
|
| 8 * Some code copyright (C) 2005, Jonathan Clark <ardentlygnarly@users.sourceforge.net> |
|
| 9 * |
|
| 10 * Most libfaim code copyright (C) 1998-2001 Adam Fritzler <afritz@auk.cx> |
|
| 11 * Some libfaim code copyright (C) 2001-2004 Mark Doliner <thekingant@users.sourceforge.net> |
|
| 12 * |
|
| 13 * This program is free software; you can redistribute it and/or modify |
|
| 14 * it under the terms of the GNU General Public License as published by |
|
| 15 * the Free Software Foundation; either version 2 of the License, or |
|
| 16 * (at your option) any later version. |
|
| 17 * |
|
| 18 * This program is distributed in the hope that it will be useful, |
|
| 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 21 * GNU General Public License for more details. |
|
| 22 * |
|
| 23 * You should have received a copy of the GNU General Public License |
|
| 24 * along with this program; if not, write to the Free Software |
|
| 25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
| 26 * |
|
| 27 */ |
|
| 28 #include "internal.h" |
|
| 29 |
|
| 30 #include "account.h" |
|
| 31 #include "accountopt.h" |
|
| 32 #include "buddyicon.h" |
|
| 33 #include "cipher.h" |
|
| 34 #include "conversation.h" |
|
| 35 #include "core.h" |
|
| 36 #include "debug.h" |
|
| 37 #include "imgstore.h" |
|
| 38 #include "network.h" |
|
| 39 #include "notify.h" |
|
| 40 #include "privacy.h" |
|
| 41 #include "prpl.h" |
|
| 42 #include "proxy.h" |
|
| 43 #include "request.h" |
|
| 44 #include "util.h" |
|
| 45 #include "version.h" |
|
| 46 |
|
| 47 #include "oscar.h" |
|
| 48 #include "peer.h" |
|
| 49 |
|
| 50 #define OSCAR_STATUS_ID_INVISIBLE "invisible" |
|
| 51 #define OSCAR_STATUS_ID_OFFLINE "offline" |
|
| 52 #define OSCAR_STATUS_ID_AVAILABLE "available" |
|
| 53 #define OSCAR_STATUS_ID_AWAY "away" |
|
| 54 #define OSCAR_STATUS_ID_DND "dnd" |
|
| 55 #define OSCAR_STATUS_ID_NA "na" |
|
| 56 #define OSCAR_STATUS_ID_OCCUPIED "occupied" |
|
| 57 #define OSCAR_STATUS_ID_FREE4CHAT "free4chat" |
|
| 58 #define OSCAR_STATUS_ID_CUSTOM "custom" |
|
| 59 |
|
| 60 #define AIMHASHDATA "http://gaim.sourceforge.net/aim_data.php3" |
|
| 61 |
|
| 62 #define OSCAR_CONNECT_STEPS 6 |
|
| 63 #define OSCAR_DEFAULT_LOGIN_SERVER "login.oscar.aol.com" |
|
| 64 #define OSCAR_DEFAULT_LOGIN_PORT 5190 |
|
| 65 #define OSCAR_DEFAULT_CUSTOM_ENCODING "ISO-8859-1" |
|
| 66 #define OSCAR_DEFAULT_AUTHORIZATION TRUE |
|
| 67 #define OSCAR_DEFAULT_HIDE_IP TRUE |
|
| 68 #define OSCAR_DEFAULT_WEB_AWARE FALSE |
|
| 69 #define OSCAR_DEFAULT_ALWAYS_USE_RV_PROXY FALSE |
|
| 70 |
|
| 71 static int caps_aim = OSCAR_CAPABILITY_CHAT | OSCAR_CAPABILITY_BUDDYICON | OSCAR_CAPABILITY_DIRECTIM | OSCAR_CAPABILITY_SENDFILE | OSCAR_CAPABILITY_INTEROPERATE | OSCAR_CAPABILITY_ICHAT; |
|
| 72 static int caps_icq = OSCAR_CAPABILITY_BUDDYICON | OSCAR_CAPABILITY_DIRECTIM | OSCAR_CAPABILITY_SENDFILE | OSCAR_CAPABILITY_ICQUTF8 | OSCAR_CAPABILITY_INTEROPERATE | OSCAR_CAPABILITY_ICHAT; |
|
| 73 |
|
| 74 static guint8 features_aim[] = {0x01, 0x01, 0x01, 0x02}; |
|
| 75 static guint8 features_icq[] = {0x01, 0x06}; |
|
| 76 static guint8 features_icq_offline[] = {0x01}; |
|
| 77 static guint8 ck[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
|
| 78 |
|
| 79 struct create_room { |
|
| 80 char *name; |
|
| 81 int exchange; |
|
| 82 }; |
|
| 83 |
|
| 84 struct oscar_ask_directim_data |
|
| 85 { |
|
| 86 OscarData *od; |
|
| 87 char *who; |
|
| 88 }; |
|
| 89 |
|
| 90 /* |
|
| 91 * Various PRPL-specific buddy info that we want to keep track of |
|
| 92 * Some other info is maintained by locate.c, and I'd like to move |
|
| 93 * the rest of this to libfaim, mostly im.c |
|
| 94 * |
|
| 95 * TODO: More of this should use the status API. |
|
| 96 */ |
|
| 97 struct buddyinfo { |
|
| 98 gboolean typingnot; |
|
| 99 guint32 ipaddr; |
|
| 100 |
|
| 101 unsigned long ico_me_len; |
|
| 102 unsigned long ico_me_csum; |
|
| 103 time_t ico_me_time; |
|
| 104 gboolean ico_informed; |
|
| 105 |
|
| 106 unsigned long ico_len; |
|
| 107 unsigned long ico_csum; |
|
| 108 time_t ico_time; |
|
| 109 gboolean ico_need; |
|
| 110 gboolean ico_sent; |
|
| 111 }; |
|
| 112 |
|
| 113 struct name_data { |
|
| 114 GaimConnection *gc; |
|
| 115 gchar *name; |
|
| 116 gchar *nick; |
|
| 117 }; |
|
| 118 |
|
| 119 static char *msgerrreason[] = { |
|
| 120 N_("Invalid error"), |
|
| 121 N_("Invalid SNAC"), |
|
| 122 N_("Rate to host"), |
|
| 123 N_("Rate to client"), |
|
| 124 N_("Not logged in"), |
|
| 125 N_("Service unavailable"), |
|
| 126 N_("Service not defined"), |
|
| 127 N_("Obsolete SNAC"), |
|
| 128 N_("Not supported by host"), |
|
| 129 N_("Not supported by client"), |
|
| 130 N_("Refused by client"), |
|
| 131 N_("Reply too big"), |
|
| 132 N_("Responses lost"), |
|
| 133 N_("Request denied"), |
|
| 134 N_("Busted SNAC payload"), |
|
| 135 N_("Insufficient rights"), |
|
| 136 N_("In local permit/deny"), |
|
| 137 N_("Too evil (sender)"), |
|
| 138 N_("Too evil (receiver)"), |
|
| 139 N_("User temporarily unavailable"), |
|
| 140 N_("No match"), |
|
| 141 N_("List overflow"), |
|
| 142 N_("Request ambiguous"), |
|
| 143 N_("Queue full"), |
|
| 144 N_("Not while on AOL") |
|
| 145 }; |
|
| 146 static int msgerrreasonlen = 25; |
|
| 147 |
|
| 148 /* All the libfaim->gaim callback functions */ |
|
| 149 static int gaim_parse_auth_resp (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 150 static int gaim_parse_login (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 151 static int gaim_parse_auth_securid_request(OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 152 static int gaim_handle_redirect (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 153 static int gaim_info_change (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 154 static int gaim_account_confirm (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 155 static int gaim_parse_oncoming (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 156 static int gaim_parse_offgoing (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 157 static int gaim_parse_incoming_im(OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 158 static int gaim_parse_misses (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 159 static int gaim_parse_clientauto (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 160 static int gaim_parse_userinfo (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 161 static int gaim_got_infoblock (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 162 static int gaim_parse_motd (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 163 static int gaim_chatnav_info (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 164 static int gaim_conv_chat_join (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 165 static int gaim_conv_chat_leave (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 166 static int gaim_conv_chat_info_update (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 167 static int gaim_conv_chat_incoming_msg(OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 168 static int gaim_email_parseupdate(OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 169 static int gaim_icon_error (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 170 static int gaim_icon_parseicon (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 171 static int oscar_icon_req (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 172 static int gaim_parse_msgack (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 173 static int gaim_parse_ratechange (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 174 static int gaim_parse_evilnotify (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 175 static int gaim_parse_searcherror(OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 176 static int gaim_parse_searchreply(OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 177 static int gaim_bosrights (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 178 static int gaim_connerr (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 179 static int gaim_parse_msgerr (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 180 static int gaim_parse_mtn (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 181 static int gaim_parse_locaterights(OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 182 static int gaim_parse_buddyrights(OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 183 static int gaim_parse_locerr (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 184 static int gaim_icbm_param_info (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 185 static int gaim_parse_genericerr (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 186 static int gaim_memrequest (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 187 static int gaim_selfinfo (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 188 static int gaim_offlinemsg (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 189 static int gaim_offlinemsgdone (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 190 static int gaim_icqalias (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 191 static int gaim_icqinfo (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 192 static int gaim_popup (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 193 static int gaim_ssi_parseerr (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 194 static int gaim_ssi_parserights (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 195 static int gaim_ssi_parselist (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 196 static int gaim_ssi_parseack (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 197 static int gaim_ssi_parseadd (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 198 static int gaim_ssi_authgiven (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 199 static int gaim_ssi_authrequest (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 200 static int gaim_ssi_authreply (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 201 static int gaim_ssi_gotadded (OscarData *, FlapConnection *, FlapFrame *, ...); |
|
| 202 |
|
| 203 static gboolean gaim_icon_timerfunc(gpointer data); |
|
| 204 |
|
| 205 static void recent_buddies_cb(const char *name, GaimPrefType type, gconstpointer value, gpointer data); |
|
| 206 static void oscar_set_info(GaimConnection *gc, const char *info); |
|
| 207 static void oscar_set_info_and_status(GaimAccount *account, gboolean setinfo, const char *rawinfo, gboolean setstatus, GaimStatus *status); |
|
| 208 static void oscar_set_extendedstatus(GaimConnection *gc); |
|
| 209 static gboolean gaim_ssi_rerequestdata(gpointer data); |
|
| 210 |
|
| 211 static void oscar_free_name_data(struct name_data *data) { |
|
| 212 g_free(data->name); |
|
| 213 g_free(data->nick); |
|
| 214 g_free(data); |
|
| 215 } |
|
| 216 |
|
| 217 /** |
|
| 218 * Determine how we can send this message. Per the warnings elsewhere |
|
| 219 * in this file, these little checks determine the simplest encoding |
|
| 220 * we can use for a given message send using it. |
|
| 221 */ |
|
| 222 static guint32 |
|
| 223 oscar_charset_check(const char *utf8) |
|
| 224 { |
|
| 225 int i = 0; |
|
| 226 int charset = AIM_CHARSET_ASCII; |
|
| 227 |
|
| 228 /* |
|
| 229 * Can we get away with using our custom encoding? |
|
| 230 */ |
|
| 231 while (utf8[i]) |
|
| 232 { |
|
| 233 if ((unsigned char)utf8[i] > 0x7f) { |
|
| 234 /* not ASCII! */ |
|
| 235 charset = AIM_CHARSET_CUSTOM; |
|
| 236 break; |
|
| 237 } |
|
| 238 i++; |
|
| 239 } |
|
| 240 |
|
| 241 /* |
|
| 242 * Must we send this message as UNICODE (in the UCS-2BE encoding)? |
|
| 243 */ |
|
| 244 while (utf8[i]) |
|
| 245 { |
|
| 246 /* ISO-8859-1 is 0x00-0xbf in the first byte |
|
| 247 * followed by 0xc0-0xc3 in the second */ |
|
| 248 if ((unsigned char)utf8[i] < 0x80) { |
|
| 249 i++; |
|
| 250 continue; |
|
| 251 } else if (((unsigned char)utf8[i] & 0xfc) == 0xc0 && |
|
| 252 ((unsigned char)utf8[i + 1] & 0xc0) == 0x80) { |
|
| 253 i += 2; |
|
| 254 continue; |
|
| 255 } |
|
| 256 charset = AIM_CHARSET_UNICODE; |
|
| 257 break; |
|
| 258 } |
|
| 259 |
|
| 260 return charset; |
|
| 261 } |
|
| 262 |
|
| 263 /** |
|
| 264 * Take a string of the form charset="bleh" where bleh is |
|
| 265 * one of us-ascii, utf-8, iso-8859-1, or unicode-2-0, and |
|
| 266 * return a newly allocated string containing bleh. |
|
| 267 */ |
|
| 268 static gchar * |
|
| 269 oscar_encoding_extract(const char *encoding) |
|
| 270 { |
|
| 271 gchar *ret = NULL; |
|
| 272 char *begin, *end; |
|
| 273 |
|
| 274 g_return_val_if_fail(encoding != NULL, NULL); |
|
| 275 |
|
| 276 /* Make sure encoding begins with charset= */ |
|
| 277 if (strncmp(encoding, "text/aolrtf; charset=", 21) && |
|
| 278 strncmp(encoding, "text/x-aolrtf; charset=", 23)) |
|
| 279 { |
|
| 280 return NULL; |
|
| 281 } |
|
| 282 |
|
| 283 begin = strchr(encoding, '"'); |
|
| 284 end = strrchr(encoding, '"'); |
|
| 285 |
|
| 286 if ((begin == NULL) || (end == NULL) || (begin >= end)) |
|
| 287 return NULL; |
|
| 288 |
|
| 289 ret = g_strndup(begin+1, (end-1) - begin); |
|
| 290 |
|
| 291 return ret; |
|
| 292 } |
|
| 293 |
|
| 294 gchar * |
|
| 295 oscar_encoding_to_utf8(const char *encoding, const char *text, int textlen) |
|
| 296 { |
|
| 297 gchar *utf8 = NULL; |
|
| 298 |
|
| 299 if ((encoding == NULL) || encoding[0] == '\0') { |
|
| 300 gaim_debug_info("oscar", "Empty encoding, assuming UTF-8\n"); |
|
| 301 } else if (!strcasecmp(encoding, "iso-8859-1")) { |
|
| 302 utf8 = g_convert(text, textlen, "UTF-8", "iso-8859-1", NULL, NULL, NULL); |
|
| 303 } else if (!strcasecmp(encoding, "ISO-8859-1-Windows-3.1-Latin-1")) { |
|
| 304 utf8 = g_convert(text, textlen, "UTF-8", "Windows-1252", NULL, NULL, NULL); |
|
| 305 } else if (!strcasecmp(encoding, "unicode-2-0")) { |
|
| 306 utf8 = g_convert(text, textlen, "UTF-8", "UCS-2BE", NULL, NULL, NULL); |
|
| 307 } else if (strcasecmp(encoding, "us-ascii") && strcmp(encoding, "utf-8")) { |
|
| 308 gaim_debug_warning("oscar", "Unrecognized character encoding \"%s\", " |
|
| 309 "attempting to convert to UTF-8 anyway\n", encoding); |
|
| 310 utf8 = g_convert(text, textlen, "UTF-8", encoding, NULL, NULL, NULL); |
|
| 311 } |
|
| 312 |
|
| 313 /* |
|
| 314 * If utf8 is still NULL then either the encoding is us-ascii/utf-8 or |
|
| 315 * we have been unable to convert the text to utf-8 from the encoding |
|
| 316 * that was specified. So we check if the text is valid utf-8 then |
|
| 317 * just copy it. |
|
| 318 */ |
|
| 319 if (utf8 == NULL) { |
|
| 320 if (textlen != 0 && *text != '\0' |
|
| 321 && !g_utf8_validate(text, textlen, NULL)) |
|
| 322 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.)")); |
|
| 323 else |
|
| 324 utf8 = g_strndup(text, textlen); |
|
| 325 } |
|
| 326 |
|
| 327 return utf8; |
|
| 328 } |
|
| 329 |
|
| 330 static gchar * |
|
| 331 oscar_utf8_try_convert(GaimAccount *account, const gchar *msg) |
|
| 332 { |
|
| 333 const char *charset = NULL; |
|
| 334 char *ret = NULL; |
|
| 335 |
|
| 336 if(aim_sn_is_icq(gaim_account_get_username(account))) |
|
| 337 charset = gaim_account_get_string(account, "encoding", NULL); |
|
| 338 |
|
| 339 if(charset && *charset) |
|
| 340 ret = g_convert(msg, -1, "UTF-8", charset, NULL, NULL, NULL); |
|
| 341 |
|
| 342 if(!ret) |
|
| 343 ret = gaim_utf8_try_convert(msg); |
|
| 344 |
|
| 345 return ret; |
|
| 346 } |
|
| 347 |
|
| 348 static gchar * |
|
| 349 gaim_plugin_oscar_convert_to_utf8(const gchar *data, gsize datalen, const char *charsetstr, gboolean fallback) |
|
| 350 { |
|
| 351 gchar *ret = NULL; |
|
| 352 GError *err = NULL; |
|
| 353 |
|
| 354 if ((charsetstr == NULL) || (*charsetstr == '\0')) |
|
| 355 return NULL; |
|
| 356 |
|
| 357 if (strcasecmp("UTF-8", charsetstr)) { |
|
| 358 if (fallback) |
|
| 359 ret = g_convert_with_fallback(data, datalen, "UTF-8", charsetstr, "?", NULL, NULL, &err); |
|
| 360 else |
|
| 361 ret = g_convert(data, datalen, "UTF-8", charsetstr, NULL, NULL, &err); |
|
| 362 if (err != NULL) { |
|
| 363 gaim_debug_warning("oscar", "Conversion from %s failed: %s.\n", |
|
| 364 charsetstr, err->message); |
|
| 365 g_error_free(err); |
|
| 366 } |
|
| 367 } else { |
|
| 368 if (g_utf8_validate(data, datalen, NULL)) |
|
| 369 ret = g_strndup(data, datalen); |
|
| 370 else |
|
| 371 gaim_debug_warning("oscar", "String is not valid UTF-8.\n"); |
|
| 372 } |
|
| 373 |
|
| 374 return ret; |
|
| 375 } |
|
| 376 |
|
| 377 /** |
|
| 378 * This attemps to decode an incoming IM into a UTF8 string. |
|
| 379 * |
|
| 380 * We try decoding using two different character sets. The charset |
|
| 381 * specified in the IM determines the order in which we attempt to |
|
| 382 * decode. We do this because there are lots of broken ICQ clients |
|
| 383 * that don't correctly send non-ASCII messages. And if Gaim isn't |
|
| 384 * able to deal with that crap, then people complain like banshees. |
|
| 385 * charsetstr1 is always set to what the correct encoding should be. |
|
| 386 */ |
|
| 387 gchar * |
|
| 388 gaim_plugin_oscar_decode_im_part(GaimAccount *account, const char *sourcesn, guint16 charset, guint16 charsubset, const gchar *data, gsize datalen) |
|
| 389 { |
|
| 390 gchar *ret = NULL; |
|
| 391 const gchar *charsetstr1, *charsetstr2; |
|
| 392 |
|
| 393 gaim_debug_info("oscar", "Parsing IM part, charset=0x%04hx, charsubset=0x%04hx, datalen=%hd\n", charset, charsubset, datalen); |
|
| 394 |
|
| 395 if ((datalen == 0) || (data == NULL)) |
|
| 396 return NULL; |
|
| 397 |
|
| 398 if (charset == AIM_CHARSET_UNICODE) { |
|
| 399 charsetstr1 = "UCS-2BE"; |
|
| 400 charsetstr2 = "UTF-8"; |
|
| 401 } else if (charset == AIM_CHARSET_CUSTOM) { |
|
| 402 if ((sourcesn != NULL) && isdigit(sourcesn[0])) |
|
| 403 charsetstr1 = gaim_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING); |
|
| 404 else |
|
| 405 charsetstr1 = "ISO-8859-1"; |
|
| 406 charsetstr2 = "UTF-8"; |
|
| 407 } else if (charset == AIM_CHARSET_ASCII) { |
|
| 408 /* Should just be "ASCII" */ |
|
| 409 charsetstr1 = "ASCII"; |
|
| 410 charsetstr2 = gaim_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING); |
|
| 411 } else if (charset == 0x000d) { |
|
| 412 /* Mobile AIM client on a Nokia 3100 and an LG VX6000 */ |
|
| 413 charsetstr1 = "ISO-8859-1"; |
|
| 414 charsetstr2 = gaim_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING); |
|
| 415 } else { |
|
| 416 /* Unknown, hope for valid UTF-8... */ |
|
| 417 charsetstr1 = "UTF-8"; |
|
| 418 charsetstr2 = gaim_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING); |
|
| 419 } |
|
| 420 |
|
| 421 ret = gaim_plugin_oscar_convert_to_utf8(data, datalen, charsetstr1, FALSE); |
|
| 422 if (ret == NULL) |
|
| 423 ret = gaim_plugin_oscar_convert_to_utf8(data, datalen, charsetstr2, TRUE); |
|
| 424 if (ret == NULL) |
|
| 425 ret = g_strdup(_("(There was an error receiving this message. The buddy you are speaking to most likely has a buggy client.)")); |
|
| 426 |
|
| 427 return ret; |
|
| 428 } |
|
| 429 |
|
| 430 /** |
|
| 431 * Figure out what encoding to use when sending a given outgoing message. |
|
| 432 */ |
|
| 433 static void |
|
| 434 gaim_plugin_oscar_convert_to_best_encoding(GaimConnection *gc, |
|
| 435 const char *destsn, const gchar *from, |
|
| 436 gchar **msg, int *msglen_int, |
|
| 437 guint16 *charset, guint16 *charsubset) |
|
| 438 { |
|
| 439 OscarData *od = gc->proto_data; |
|
| 440 GaimAccount *account = gaim_connection_get_account(gc); |
|
| 441 GError *err = NULL; |
|
| 442 aim_userinfo_t *userinfo = NULL; |
|
| 443 const gchar *charsetstr; |
|
| 444 gsize msglen; |
|
| 445 |
|
| 446 /* Attempt to send as ASCII */ |
|
| 447 if (oscar_charset_check(from) == AIM_CHARSET_ASCII) { |
|
| 448 *msg = g_convert(from, strlen(from), "ASCII", "UTF-8", NULL, &msglen, NULL); |
|
| 449 *charset = AIM_CHARSET_ASCII; |
|
| 450 *charsubset = 0x0000; |
|
| 451 *msglen_int = msglen; |
|
| 452 return; |
|
| 453 } |
|
| 454 |
|
| 455 /* |
|
| 456 * If we're sending to an ICQ user, and they are in our |
|
| 457 * buddy list, and they are advertising the Unicode |
|
| 458 * capability, and they are online, then attempt to send |
|
| 459 * as UCS-2BE. |
|
| 460 */ |
|
| 461 if ((destsn != NULL) && aim_sn_is_icq(destsn)) |
|
| 462 userinfo = aim_locate_finduserinfo(od, destsn); |
|
| 463 |
|
| 464 if ((userinfo != NULL) && (userinfo->capabilities & OSCAR_CAPABILITY_ICQUTF8)) |
|
| 465 { |
|
| 466 GaimBuddy *b; |
|
| 467 b = gaim_find_buddy(account, destsn); |
|
| 468 if ((b != NULL) && (GAIM_BUDDY_IS_ONLINE(b))) |
|
| 469 { |
|
| 470 *msg = g_convert(from, strlen(from), "UCS-2BE", "UTF-8", NULL, &msglen, NULL); |
|
| 471 if (*msg != NULL) |
|
| 472 { |
|
| 473 *charset = AIM_CHARSET_UNICODE; |
|
| 474 *charsubset = 0x0000; |
|
| 475 *msglen_int = msglen; |
|
| 476 return; |
|
| 477 } |
|
| 478 } |
|
| 479 } |
|
| 480 |
|
| 481 /* |
|
| 482 * If this is AIM then attempt to send as ISO-8859-1. If this is |
|
| 483 * ICQ then attempt to send as the user specified character encoding. |
|
| 484 */ |
|
| 485 charsetstr = "ISO-8859-1"; |
|
| 486 if ((destsn != NULL) && aim_sn_is_icq(destsn)) |
|
| 487 charsetstr = gaim_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING); |
|
| 488 |
|
| 489 /* |
|
| 490 * XXX - We need a way to only attempt to convert if we KNOW "from" |
|
| 491 * can be converted to "charsetstr" |
|
| 492 */ |
|
| 493 *msg = g_convert(from, strlen(from), charsetstr, "UTF-8", NULL, &msglen, NULL); |
|
| 494 if (*msg != NULL) { |
|
| 495 *charset = AIM_CHARSET_CUSTOM; |
|
| 496 *charsubset = 0x0000; |
|
| 497 *msglen_int = msglen; |
|
| 498 return; |
|
| 499 } |
|
| 500 |
|
| 501 /* |
|
| 502 * Nothing else worked, so send as UCS-2BE. |
|
| 503 */ |
|
| 504 *msg = g_convert(from, strlen(from), "UCS-2BE", "UTF-8", NULL, &msglen, &err); |
|
| 505 if (*msg != NULL) { |
|
| 506 *charset = AIM_CHARSET_UNICODE; |
|
| 507 *charsubset = 0x0000; |
|
| 508 *msglen_int = msglen; |
|
| 509 return; |
|
| 510 } |
|
| 511 |
|
| 512 gaim_debug_error("oscar", "Error converting a Unicode message: %s\n", err->message); |
|
| 513 g_error_free(err); |
|
| 514 |
|
| 515 gaim_debug_error("oscar", "This should NEVER happen! Sending UTF-8 text flagged as ASCII.\n"); |
|
| 516 *msg = g_strdup(from); |
|
| 517 *msglen_int = strlen(*msg); |
|
| 518 *charset = AIM_CHARSET_ASCII; |
|
| 519 *charsubset = 0x0000; |
|
| 520 return; |
|
| 521 } |
|
| 522 |
|
| 523 /** |
|
| 524 * Looks for %n, %d, or %t in a string, and replaces them with the |
|
| 525 * specified name, date, and time, respectively. |
|
| 526 * |
|
| 527 * @param str The string that may contain the special variables. |
|
| 528 * @param name The sender name. |
|
| 529 * |
|
| 530 * @return A newly allocated string where the special variables are |
|
| 531 * expanded. This should be g_free'd by the caller. |
|
| 532 */ |
|
| 533 static gchar * |
|
| 534 gaim_str_sub_away_formatters(const char *str, const char *name) |
|
| 535 { |
|
| 536 char *c; |
|
| 537 GString *cpy; |
|
| 538 time_t t; |
|
| 539 struct tm *tme; |
|
| 540 |
|
| 541 g_return_val_if_fail(str != NULL, NULL); |
|
| 542 g_return_val_if_fail(name != NULL, NULL); |
|
| 543 |
|
| 544 /* Create an empty GString that is hopefully big enough for most messages */ |
|
| 545 cpy = g_string_sized_new(1024); |
|
| 546 |
|
| 547 t = time(NULL); |
|
| 548 tme = localtime(&t); |
|
| 549 |
|
| 550 c = (char *)str; |
|
| 551 while (*c) { |
|
| 552 switch (*c) { |
|
| 553 case '%': |
|
| 554 if (*(c + 1)) { |
|
| 555 switch (*(c + 1)) { |
|
| 556 case 'n': |
|
| 557 /* append name */ |
|
| 558 g_string_append(cpy, name); |
|
| 559 c++; |
|
| 560 break; |
|
| 561 case 'd': |
|
| 562 /* append date */ |
|
| 563 g_string_append(cpy, gaim_date_format_short(tme)); |
|
| 564 c++; |
|
| 565 break; |
|
| 566 case 't': |
|
| 567 /* append time */ |
|
| 568 g_string_append(cpy, gaim_time_format(tme)); |
|
| 569 c++; |
|
| 570 break; |
|
| 571 default: |
|
| 572 g_string_append_c(cpy, *c); |
|
| 573 } |
|
| 574 } else { |
|
| 575 g_string_append_c(cpy, *c); |
|
| 576 } |
|
| 577 break; |
|
| 578 default: |
|
| 579 g_string_append_c(cpy, *c); |
|
| 580 } |
|
| 581 c++; |
|
| 582 } |
|
| 583 |
|
| 584 return g_string_free(cpy, FALSE); |
|
| 585 } |
|
| 586 |
|
| 587 static gchar *oscar_caps_to_string(guint caps) |
|
| 588 { |
|
| 589 GString *str; |
|
| 590 const gchar *tmp; |
|
| 591 guint bit = 1; |
|
| 592 |
|
| 593 str = g_string_new(""); |
|
| 594 |
|
| 595 if (!caps) { |
|
| 596 return NULL; |
|
| 597 } else while (bit <= OSCAR_CAPABILITY_LAST) { |
|
| 598 if (bit & caps) { |
|
| 599 switch (bit) { |
|
| 600 case OSCAR_CAPABILITY_BUDDYICON: |
|
| 601 tmp = _("Buddy Icon"); |
|
| 602 break; |
|
| 603 case OSCAR_CAPABILITY_TALK: |
|
| 604 tmp = _("Voice"); |
|
| 605 break; |
|
| 606 case OSCAR_CAPABILITY_DIRECTIM: |
|
| 607 tmp = _("AIM Direct IM"); |
|
| 608 break; |
|
| 609 case OSCAR_CAPABILITY_CHAT: |
|
| 610 tmp = _("Chat"); |
|
| 611 break; |
|
| 612 case OSCAR_CAPABILITY_GETFILE: |
|
| 613 tmp = _("Get File"); |
|
| 614 break; |
|
| 615 case OSCAR_CAPABILITY_SENDFILE: |
|
| 616 tmp = _("Send File"); |
|
| 617 break; |
|
| 618 case OSCAR_CAPABILITY_GAMES: |
|
| 619 case OSCAR_CAPABILITY_GAMES2: |
|
| 620 tmp = _("Games"); |
|
| 621 break; |
|
| 622 case OSCAR_CAPABILITY_ADDINS: |
|
| 623 tmp = _("Add-Ins"); |
|
| 624 break; |
|
| 625 case OSCAR_CAPABILITY_SENDBUDDYLIST: |
|
| 626 tmp = _("Send Buddy List"); |
|
| 627 break; |
|
| 628 case OSCAR_CAPABILITY_ICQ_DIRECT: |
|
| 629 tmp = _("ICQ Direct Connect"); |
|
| 630 break; |
|
| 631 case OSCAR_CAPABILITY_APINFO: |
|
| 632 tmp = _("AP User"); |
|
| 633 break; |
|
| 634 case OSCAR_CAPABILITY_ICQRTF: |
|
| 635 tmp = _("ICQ RTF"); |
|
| 636 break; |
|
| 637 case OSCAR_CAPABILITY_EMPTY: |
|
| 638 tmp = _("Nihilist"); |
|
| 639 break; |
|
| 640 case OSCAR_CAPABILITY_ICQSERVERRELAY: |
|
| 641 tmp = _("ICQ Server Relay"); |
|
| 642 break; |
|
| 643 case OSCAR_CAPABILITY_ICQUTF8OLD: |
|
| 644 tmp = _("Old ICQ UTF8"); |
|
| 645 break; |
|
| 646 case OSCAR_CAPABILITY_TRILLIANCRYPT: |
|
| 647 tmp = _("Trillian Encryption"); |
|
| 648 break; |
|
| 649 case OSCAR_CAPABILITY_ICQUTF8: |
|
| 650 tmp = _("ICQ UTF8"); |
|
| 651 break; |
|
| 652 case OSCAR_CAPABILITY_HIPTOP: |
|
| 653 tmp = _("Hiptop"); |
|
| 654 break; |
|
| 655 case OSCAR_CAPABILITY_SECUREIM: |
|
| 656 tmp = _("Security Enabled"); |
|
| 657 break; |
|
| 658 case OSCAR_CAPABILITY_VIDEO: |
|
| 659 tmp = _("Video Chat"); |
|
| 660 break; |
|
| 661 /* Not actually sure about this one... WinAIM doesn't show anything */ |
|
| 662 case OSCAR_CAPABILITY_ICHATAV: |
|
| 663 tmp = _("iChat AV"); |
|
| 664 break; |
|
| 665 case OSCAR_CAPABILITY_LIVEVIDEO: |
|
| 666 tmp = _("Live Video"); |
|
| 667 break; |
|
| 668 case OSCAR_CAPABILITY_CAMERA: |
|
| 669 tmp = _("Camera"); |
|
| 670 break; |
|
| 671 default: |
|
| 672 tmp = NULL; |
|
| 673 break; |
|
| 674 } |
|
| 675 if (tmp) |
|
| 676 g_string_append_printf(str, "%s%s", (*(str->str) == '\0' ? "" : ", "), tmp); |
|
| 677 } |
|
| 678 bit <<= 1; |
|
| 679 } |
|
| 680 |
|
| 681 return g_string_free(str, FALSE); |
|
| 682 } |
|
| 683 |
|
| 684 static char *oscar_icqstatus(int state) { |
|
| 685 /* Make a cute little string that shows the status of the dude or dudet */ |
|
| 686 if (state & AIM_ICQ_STATE_CHAT) |
|
| 687 return g_strdup_printf(_("Free For Chat")); |
|
| 688 else if (state & AIM_ICQ_STATE_DND) |
|
| 689 return g_strdup_printf(_("Do Not Disturb")); |
|
| 690 else if (state & AIM_ICQ_STATE_OUT) |
|
| 691 return g_strdup_printf(_("Not Available")); |
|
| 692 else if (state & AIM_ICQ_STATE_BUSY) |
|
| 693 return g_strdup_printf(_("Occupied")); |
|
| 694 else if (state & AIM_ICQ_STATE_AWAY) |
|
| 695 return g_strdup_printf(_("Away")); |
|
| 696 else if (state & AIM_ICQ_STATE_WEBAWARE) |
|
| 697 return g_strdup_printf(_("Web Aware")); |
|
| 698 else if (state & AIM_ICQ_STATE_INVISIBLE) |
|
| 699 return g_strdup_printf(_("Invisible")); |
|
| 700 else |
|
| 701 return g_strdup_printf(_("Online")); |
|
| 702 } |
|
| 703 |
|
| 704 static void |
|
| 705 oscar_string_append(GString *str, const char *newline, |
|
| 706 const char *name, const char *value) |
|
| 707 { |
|
| 708 if (value && value[0]) { |
|
| 709 g_string_append_printf(str, "%s<b>%s:</b> %s", newline, name, value); |
|
| 710 } |
|
| 711 } |
|
| 712 |
|
| 713 static void |
|
| 714 oscar_string_convert_and_append(GaimAccount *account, GString *str, const char *newline, |
|
| 715 const char *name, const char *value) |
|
| 716 { |
|
| 717 gchar *utf8; |
|
| 718 |
|
| 719 if (value && value[0] && (utf8 = oscar_utf8_try_convert(account, value))) { |
|
| 720 g_string_append_printf(str, "%s<b>%s:</b> %s", newline, name, utf8); |
|
| 721 g_free(utf8); |
|
| 722 } |
|
| 723 } |
|
| 724 |
|
| 725 static void oscar_string_append_info(GaimConnection *gc, GString *str, const char *newline, GaimBuddy *b, aim_userinfo_t *userinfo) |
|
| 726 { |
|
| 727 OscarData *od; |
|
| 728 GaimAccount *account; |
|
| 729 GaimPresence *presence = NULL; |
|
| 730 GaimStatus *status = NULL; |
|
| 731 GaimGroup *g = NULL; |
|
| 732 struct buddyinfo *bi = NULL; |
|
| 733 char *tmp; |
|
| 734 |
|
| 735 od = gc->proto_data; |
|
| 736 account = gaim_connection_get_account(gc); |
|
| 737 |
|
| 738 if ((str == NULL) || (newline == NULL) || ((b == NULL) && (userinfo == NULL))) |
|
| 739 return; |
|
| 740 |
|
| 741 if (userinfo == NULL) |
|
| 742 userinfo = aim_locate_finduserinfo(od, b->name); |
|
| 743 |
|
| 744 if (b == NULL) |
|
| 745 b = gaim_find_buddy(account, userinfo->sn); |
|
| 746 |
|
| 747 if (b != NULL) { |
|
| 748 g = gaim_buddy_get_group(b); |
|
| 749 presence = gaim_buddy_get_presence(b); |
|
| 750 status = gaim_presence_get_active_status(presence); |
|
| 751 } |
|
| 752 |
|
| 753 if (userinfo != NULL) |
|
| 754 bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(account, userinfo->sn)); |
|
| 755 |
|
| 756 if (b != NULL) { |
|
| 757 if (gaim_presence_is_online(presence)) { |
|
| 758 if (aim_sn_is_icq(b->name)) { |
|
| 759 GaimStatus *status = gaim_presence_get_active_status(presence); |
|
| 760 oscar_string_append(str, newline, _("Status"), |
|
| 761 gaim_status_get_name(status)); |
|
| 762 } |
|
| 763 } else { |
|
| 764 tmp = aim_ssi_itemlist_findparentname(od->ssi.local, b->name); |
|
| 765 if (aim_ssi_waitingforauth(od->ssi.local, tmp, b->name)) |
|
| 766 oscar_string_append(str, newline, _("Status"), |
|
| 767 _("Not Authorized")); |
|
| 768 else |
|
| 769 oscar_string_append(str, newline, _("Status"), |
|
| 770 _("Offline")); |
|
| 771 } |
|
| 772 } |
|
| 773 |
|
| 774 if ((bi != NULL) && (bi->ipaddr != 0)) { |
|
| 775 tmp = g_strdup_printf("%hhu.%hhu.%hhu.%hhu", |
|
| 776 (bi->ipaddr & 0xff000000) >> 24, |
|
| 777 (bi->ipaddr & 0x00ff0000) >> 16, |
|
| 778 (bi->ipaddr & 0x0000ff00) >> 8, |
|
| 779 (bi->ipaddr & 0x000000ff)); |
|
| 780 oscar_string_append(str, newline, _("IP Address"), tmp); |
|
| 781 g_free(tmp); |
|
| 782 } |
|
| 783 |
|
| 784 |
|
| 785 if ((userinfo != NULL) && (userinfo->warnlevel != 0)) { |
|
| 786 tmp = g_strdup_printf("%d", (int)(userinfo->warnlevel/10.0 + .5)); |
|
| 787 oscar_string_append(str, newline, _("Warning Level"), tmp); |
|
| 788 g_free(tmp); |
|
| 789 } |
|
| 790 |
|
| 791 if ((b != NULL) && (b->name != NULL) && (g != NULL) && (g->name != NULL)) { |
|
| 792 tmp = aim_ssi_getcomment(od->ssi.local, g->name, b->name); |
|
| 793 if (tmp != NULL) { |
|
| 794 char *tmp2 = g_markup_escape_text(tmp, strlen(tmp)); |
|
| 795 g_free(tmp); |
|
| 796 oscar_string_convert_and_append(account, str, newline, _("Buddy Comment"), tmp2); |
|
| 797 g_free(tmp2); |
|
| 798 } |
|
| 799 } |
|
| 800 } |
|
| 801 |
|
| 802 static char *extract_name(const char *name) { |
|
| 803 char *tmp, *x; |
|
| 804 int i, j; |
|
| 805 |
|
| 806 if (!name) |
|
| 807 return NULL; |
|
| 808 |
|
| 809 x = strchr(name, '-'); |
|
| 810 |
|
| 811 if (!x) return NULL; |
|
| 812 x = strchr(++x, '-'); |
|
| 813 if (!x) return NULL; |
|
| 814 tmp = g_strdup(++x); |
|
| 815 |
|
| 816 for (i = 0, j = 0; x[i]; i++) { |
|
| 817 char hex[3]; |
|
| 818 if (x[i] != '%') { |
|
| 819 tmp[j++] = x[i]; |
|
| 820 continue; |
|
| 821 } |
|
| 822 strncpy(hex, x + ++i, 2); hex[2] = 0; |
|
| 823 i++; |
|
| 824 tmp[j++] = strtol(hex, NULL, 16); |
|
| 825 } |
|
| 826 |
|
| 827 tmp[j] = 0; |
|
| 828 return tmp; |
|
| 829 } |
|
| 830 |
|
| 831 static struct chat_connection * |
|
| 832 find_oscar_chat(GaimConnection *gc, int id) |
|
| 833 { |
|
| 834 OscarData *od = (OscarData *)gc->proto_data; |
|
| 835 GSList *cur; |
|
| 836 struct chat_connection *cc; |
|
| 837 |
|
| 838 for (cur = od->oscar_chats; cur != NULL; cur = cur->next) |
|
| 839 { |
|
| 840 cc = (struct chat_connection *)cur->data; |
|
| 841 if (cc->id == id) |
|
| 842 return cc; |
|
| 843 } |
|
| 844 |
|
| 845 return NULL; |
|
| 846 } |
|
| 847 |
|
| 848 static struct chat_connection * |
|
| 849 find_oscar_chat_by_conn(GaimConnection *gc, FlapConnection *conn) |
|
| 850 { |
|
| 851 OscarData *od = (OscarData *)gc->proto_data; |
|
| 852 GSList *cur; |
|
| 853 struct chat_connection *cc; |
|
| 854 |
|
| 855 for (cur = od->oscar_chats; cur != NULL; cur = cur->next) |
|
| 856 { |
|
| 857 cc = (struct chat_connection *)cur->data; |
|
| 858 if (cc->conn == conn) |
|
| 859 return cc; |
|
| 860 } |
|
| 861 |
|
| 862 return NULL; |
|
| 863 } |
|
| 864 |
|
| 865 static struct chat_connection * |
|
| 866 find_oscar_chat_by_conv(GaimConnection *gc, GaimConversation *conv) |
|
| 867 { |
|
| 868 OscarData *od = (OscarData *)gc->proto_data; |
|
| 869 GSList *cur; |
|
| 870 struct chat_connection *cc; |
|
| 871 |
|
| 872 for (cur = od->oscar_chats; cur != NULL; cur = cur->next) |
|
| 873 { |
|
| 874 cc = (struct chat_connection *)cur->data; |
|
| 875 if (cc->conv == conv) |
|
| 876 return cc; |
|
| 877 } |
|
| 878 |
|
| 879 return NULL; |
|
| 880 } |
|
| 881 |
|
| 882 void |
|
| 883 oscar_chat_destroy(struct chat_connection *cc) |
|
| 884 { |
|
| 885 g_free(cc->name); |
|
| 886 g_free(cc->show); |
|
| 887 g_free(cc); |
|
| 888 } |
|
| 889 |
|
| 890 static void |
|
| 891 oscar_chat_kill(GaimConnection *gc, struct chat_connection *cc) |
|
| 892 { |
|
| 893 OscarData *od = (OscarData *)gc->proto_data; |
|
| 894 |
|
| 895 /* Notify the conversation window that we've left the chat */ |
|
| 896 serv_got_chat_left(gc, gaim_conv_chat_get_id(GAIM_CONV_CHAT(cc->conv))); |
|
| 897 |
|
| 898 /* Destroy the chat_connection */ |
|
| 899 od->oscar_chats = g_slist_remove(od->oscar_chats, cc); |
|
| 900 flap_connection_schedule_destroy(cc->conn, OSCAR_DISCONNECT_DONE); |
|
| 901 oscar_chat_destroy(cc); |
|
| 902 } |
|
| 903 |
|
| 904 /** |
|
| 905 * This is the callback function anytime gaim_proxy_connect() |
|
| 906 * establishes a new TCP connection with an oscar host. Depending |
|
| 907 * on the type of host, we do a few different things here. |
|
| 908 */ |
|
| 909 static void |
|
| 910 connection_established_cb(gpointer data, gint source, const gchar *error_message) |
|
| 911 { |
|
| 912 GaimConnection *gc; |
|
| 913 OscarData *od; |
|
| 914 GaimAccount *account; |
|
| 915 FlapConnection *conn; |
|
| 916 |
|
| 917 conn = data; |
|
| 918 od = conn->od; |
|
| 919 gc = od->gc; |
|
| 920 account = gaim_connection_get_account(gc); |
|
| 921 |
|
| 922 conn->connect_info = NULL; |
|
| 923 conn->fd = source; |
|
| 924 |
|
| 925 if (source < 0) |
|
| 926 { |
|
| 927 gaim_debug_error("oscar", "unable to connect FLAP server " |
|
| 928 "of type 0x%04hx\n", conn->type); |
|
| 929 if (conn->type == SNAC_FAMILY_AUTH) |
|
| 930 gaim_connection_error(gc, _("Could not connect to authentication server")); |
|
| 931 if (conn->type == SNAC_FAMILY_LOCATE) |
|
| 932 gaim_connection_error(gc, _("Could not connect to BOS server")); |
|
| 933 else /* Maybe we should call this for BOS connections, too? */ |
|
| 934 flap_connection_schedule_destroy(conn, |
|
| 935 OSCAR_DISCONNECT_COULD_NOT_CONNECT); |
|
| 936 return; |
|
| 937 } |
|
| 938 |
|
| 939 gaim_debug_info("oscar", "connected to FLAP server of type 0x%04hx\n", |
|
| 940 conn->type); |
|
| 941 conn->watcher_incoming = gaim_input_add(conn->fd, |
|
| 942 GAIM_INPUT_READ, flap_connection_recv_cb, conn); |
|
| 943 if (conn->cookie == NULL) |
|
| 944 { |
|
| 945 if (!aim_sn_is_icq(gaim_account_get_username(account))) |
|
| 946 /* |
|
| 947 * We don't send this when authenticating an ICQ account |
|
| 948 * because for some reason ICQ is still using the |
|
| 949 * assy/insecure authentication procedure. |
|
| 950 */ |
|
| 951 flap_connection_send_version(od, conn); |
|
| 952 } |
|
| 953 else |
|
| 954 { |
|
| 955 flap_connection_send_version_with_cookie(od, conn, |
|
| 956 conn->cookielen, conn->cookie); |
|
| 957 g_free(conn->cookie); |
|
| 958 conn->cookie = NULL; |
|
| 959 } |
|
| 960 |
|
| 961 if (conn->type == SNAC_FAMILY_AUTH) |
|
| 962 { |
|
| 963 aim_request_login(od, conn, gaim_account_get_username(account)); |
|
| 964 gaim_debug_info("oscar", "Screen name sent, waiting for response\n"); |
|
| 965 gaim_connection_update_progress(gc, _("Screen name sent"), 1, OSCAR_CONNECT_STEPS); |
|
| 966 ck[1] = 0x65; |
|
| 967 } |
|
| 968 else if (conn->type == SNAC_FAMILY_LOCATE) |
|
| 969 { |
|
| 970 gaim_connection_update_progress(gc, _("Connection established, cookie sent"), 4, OSCAR_CONNECT_STEPS); |
|
| 971 ck[4] = 0x61; |
|
| 972 } |
|
| 973 else if (conn->type == SNAC_FAMILY_CHAT) |
|
| 974 { |
|
| 975 od->oscar_chats = g_slist_append(od->oscar_chats, conn->connect_data); |
|
| 976 conn->connect_data = NULL; |
|
| 977 } |
|
| 978 } |
|
| 979 |
|
| 980 static void |
|
| 981 flap_connection_established_bos(OscarData *od, FlapConnection *conn) |
|
| 982 { |
|
| 983 GaimConnection *gc = od->gc; |
|
| 984 |
|
| 985 aim_reqpersonalinfo(od, conn); |
|
| 986 |
|
| 987 gaim_debug_info("oscar", "ssi: requesting rights and list\n"); |
|
| 988 aim_ssi_reqrights(od); |
|
| 989 aim_ssi_reqdata(od); |
|
| 990 if (od->getblisttimer > 0) |
|
| 991 gaim_timeout_remove(od->getblisttimer); |
|
| 992 od->getblisttimer = gaim_timeout_add(30000, gaim_ssi_rerequestdata, od); |
|
| 993 |
|
| 994 aim_locate_reqrights(od); |
|
| 995 aim_buddylist_reqrights(od, conn); |
|
| 996 aim_im_reqparams(od); |
|
| 997 aim_bos_reqrights(od, conn); /* TODO: Don't call this with ssi */ |
|
| 998 |
|
| 999 gaim_connection_update_progress(gc, _("Finalizing connection"), 5, OSCAR_CONNECT_STEPS); |
|
| 1000 } |
|
| 1001 |
|
| 1002 static void |
|
| 1003 flap_connection_established_admin(OscarData *od, FlapConnection *conn) |
|
| 1004 { |
|
| 1005 aim_clientready(od, conn); |
|
| 1006 gaim_debug_info("oscar", "connected to admin\n"); |
|
| 1007 |
|
| 1008 if (od->chpass) { |
|
| 1009 gaim_debug_info("oscar", "changing password\n"); |
|
| 1010 aim_admin_changepasswd(od, conn, od->newp, od->oldp); |
|
| 1011 g_free(od->oldp); |
|
| 1012 od->oldp = NULL; |
|
| 1013 g_free(od->newp); |
|
| 1014 od->newp = NULL; |
|
| 1015 od->chpass = FALSE; |
|
| 1016 } |
|
| 1017 if (od->setnick) { |
|
| 1018 gaim_debug_info("oscar", "formatting screen name\n"); |
|
| 1019 aim_admin_setnick(od, conn, od->newsn); |
|
| 1020 g_free(od->newsn); |
|
| 1021 od->newsn = NULL; |
|
| 1022 od->setnick = FALSE; |
|
| 1023 } |
|
| 1024 if (od->conf) { |
|
| 1025 gaim_debug_info("oscar", "confirming account\n"); |
|
| 1026 aim_admin_reqconfirm(od, conn); |
|
| 1027 od->conf = FALSE; |
|
| 1028 } |
|
| 1029 if (od->reqemail) { |
|
| 1030 gaim_debug_info("oscar", "requesting e-mail address\n"); |
|
| 1031 aim_admin_getinfo(od, conn, 0x0011); |
|
| 1032 od->reqemail = FALSE; |
|
| 1033 } |
|
| 1034 if (od->setemail) { |
|
| 1035 gaim_debug_info("oscar", "setting e-mail address\n"); |
|
| 1036 aim_admin_setemail(od, conn, od->email); |
|
| 1037 g_free(od->email); |
|
| 1038 od->email = NULL; |
|
| 1039 od->setemail = FALSE; |
|
| 1040 } |
|
| 1041 } |
|
| 1042 |
|
| 1043 static void |
|
| 1044 flap_connection_established_chat(OscarData *od, FlapConnection *conn) |
|
| 1045 { |
|
| 1046 GaimConnection *gc = od->gc; |
|
| 1047 struct chat_connection *chatcon; |
|
| 1048 static int id = 1; |
|
| 1049 |
|
| 1050 aim_clientready(od, conn); |
|
| 1051 |
|
| 1052 chatcon = find_oscar_chat_by_conn(gc, conn); |
|
| 1053 chatcon->id = id; |
|
| 1054 chatcon->conv = serv_got_joined_chat(gc, id++, chatcon->show); |
|
| 1055 } |
|
| 1056 |
|
| 1057 static void |
|
| 1058 flap_connection_established_chatnav(OscarData *od, FlapConnection *conn) |
|
| 1059 { |
|
| 1060 aim_clientready(od, conn); |
|
| 1061 aim_chatnav_reqrights(od, conn); |
|
| 1062 } |
|
| 1063 |
|
| 1064 static void |
|
| 1065 flap_connection_established_alert(OscarData *od, FlapConnection *conn) |
|
| 1066 { |
|
| 1067 aim_email_sendcookies(od); |
|
| 1068 aim_email_activate(od); |
|
| 1069 aim_clientready(od, conn); |
|
| 1070 } |
|
| 1071 |
|
| 1072 static void |
|
| 1073 flap_connection_established_bart(OscarData *od, FlapConnection *conn) |
|
| 1074 { |
|
| 1075 GaimConnection *gc = od->gc; |
|
| 1076 |
|
| 1077 aim_clientready(od, conn); |
|
| 1078 |
|
| 1079 od->iconconnecting = FALSE; |
|
| 1080 |
|
| 1081 if (od->icontimer == 0) |
|
| 1082 od->icontimer = gaim_timeout_add(100, gaim_icon_timerfunc, gc); |
|
| 1083 } |
|
| 1084 |
|
| 1085 static int |
|
| 1086 flap_connection_established(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) |
|
| 1087 { |
|
| 1088 gaim_debug_info("oscar", "FLAP connection of type 0x%04hx is " |
|
| 1089 "now fully connected\n", conn->type); |
|
| 1090 if (conn->type == SNAC_FAMILY_LOCATE) |
|
| 1091 flap_connection_established_bos(od, conn); |
|
| 1092 else if (conn->type == SNAC_FAMILY_ADMIN) |
|
| 1093 flap_connection_established_admin(od, conn); |
|
| 1094 else if (conn->type == SNAC_FAMILY_CHAT) |
|
| 1095 flap_connection_established_chat(od, conn); |
|
| 1096 else if (conn->type == SNAC_FAMILY_CHATNAV) |
|
| 1097 flap_connection_established_chatnav(od, conn); |
|
| 1098 else if (conn->type == SNAC_FAMILY_ALERT) |
|
| 1099 flap_connection_established_alert(od, conn); |
|
| 1100 else if (conn->type == SNAC_FAMILY_BART) |
|
| 1101 flap_connection_established_bart(od, conn); |
|
| 1102 |
|
| 1103 return 1; |
|
| 1104 } |
|
| 1105 |
|
| 1106 static void |
|
| 1107 oscar_login(GaimAccount *account) |
|
| 1108 { |
|
| 1109 GaimConnection *gc; |
|
| 1110 OscarData *od; |
|
| 1111 FlapConnection *newconn; |
|
| 1112 |
|
| 1113 gc = gaim_account_get_connection(account); |
|
| 1114 od = gc->proto_data = oscar_data_new(); |
|
| 1115 od->gc = gc; |
|
| 1116 |
|
| 1117 oscar_data_addhandler(od, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0); |
|
| 1118 oscar_data_addhandler(od, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, flap_connection_established, 0); |
|
| 1119 |
|
| 1120 oscar_data_addhandler(od, SNAC_FAMILY_ADMIN, 0x0003, gaim_info_change, 0); |
|
| 1121 oscar_data_addhandler(od, SNAC_FAMILY_ADMIN, 0x0005, gaim_info_change, 0); |
|
| 1122 oscar_data_addhandler(od, SNAC_FAMILY_ADMIN, 0x0007, gaim_account_confirm, 0); |
|
| 1123 oscar_data_addhandler(od, SNAC_FAMILY_ALERT, 0x0001, gaim_parse_genericerr, 0); |
|
| 1124 oscar_data_addhandler(od, SNAC_FAMILY_ALERT, SNAC_SUBTYPE_ALERT_MAILSTATUS, gaim_email_parseupdate, 0); |
|
| 1125 oscar_data_addhandler(od, SNAC_FAMILY_AUTH, 0x0003, gaim_parse_auth_resp, 0); |
|
| 1126 oscar_data_addhandler(od, SNAC_FAMILY_AUTH, 0x0007, gaim_parse_login, 0); |
|
| 1127 oscar_data_addhandler(od, SNAC_FAMILY_AUTH, SNAC_SUBTYPE_AUTH_SECURID_REQUEST, gaim_parse_auth_securid_request, 0); |
|
| 1128 oscar_data_addhandler(od, SNAC_FAMILY_BART, SNAC_SUBTYPE_BART_ERROR, gaim_icon_error, 0); |
|
| 1129 oscar_data_addhandler(od, SNAC_FAMILY_BART, SNAC_SUBTYPE_BART_RESPONSE, gaim_icon_parseicon, 0); |
|
| 1130 oscar_data_addhandler(od, SNAC_FAMILY_BOS, 0x0001, gaim_parse_genericerr, 0); |
|
| 1131 oscar_data_addhandler(od, SNAC_FAMILY_BOS, 0x0003, gaim_bosrights, 0); |
|
| 1132 oscar_data_addhandler(od, SNAC_FAMILY_BUDDY, 0x0001, gaim_parse_genericerr, 0); |
|
| 1133 oscar_data_addhandler(od, SNAC_FAMILY_BUDDY, SNAC_SUBTYPE_BUDDY_RIGHTSINFO, gaim_parse_buddyrights, 0); |
|
| 1134 oscar_data_addhandler(od, SNAC_FAMILY_BUDDY, SNAC_SUBTYPE_BUDDY_ONCOMING, gaim_parse_oncoming, 0); |
|
| 1135 oscar_data_addhandler(od, SNAC_FAMILY_BUDDY, SNAC_SUBTYPE_BUDDY_OFFGOING, gaim_parse_offgoing, 0); |
|
| 1136 oscar_data_addhandler(od, SNAC_FAMILY_CHAT, 0x0001, gaim_parse_genericerr, 0); |
|
| 1137 oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_USERJOIN, gaim_conv_chat_join, 0); |
|
| 1138 oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_USERLEAVE, gaim_conv_chat_leave, 0); |
|
| 1139 oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_ROOMINFOUPDATE, gaim_conv_chat_info_update, 0); |
|
| 1140 oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_INCOMINGMSG, gaim_conv_chat_incoming_msg, 0); |
|
| 1141 oscar_data_addhandler(od, SNAC_FAMILY_CHATNAV, 0x0001, gaim_parse_genericerr, 0); |
|
| 1142 oscar_data_addhandler(od, SNAC_FAMILY_CHATNAV, SNAC_SUBTYPE_CHATNAV_INFO, gaim_chatnav_info, 0); |
|
| 1143 oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_ERROR, gaim_ssi_parseerr, 0); |
|
| 1144 oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_RIGHTSINFO, gaim_ssi_parserights, 0); |
|
| 1145 oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_LIST, gaim_ssi_parselist, 0); |
|
| 1146 oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_SRVACK, gaim_ssi_parseack, 0); |
|
| 1147 oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_ADD, gaim_ssi_parseadd, 0); |
|
| 1148 oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_RECVAUTH, gaim_ssi_authgiven, 0); |
|
| 1149 oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_RECVAUTHREQ, gaim_ssi_authrequest, 0); |
|
| 1150 oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_RECVAUTHREP, gaim_ssi_authreply, 0); |
|
| 1151 oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_ADDED, gaim_ssi_gotadded, 0); |
|
| 1152 oscar_data_addhandler(od, SNAC_FAMILY_ICBM, 0x0005, gaim_icbm_param_info, 0); |
|
| 1153 oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_INCOMING, gaim_parse_incoming_im, 0); |
|
| 1154 oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_MISSEDCALL, gaim_parse_misses, 0); |
|
| 1155 oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_CLIENTAUTORESP, gaim_parse_clientauto, 0); |
|
| 1156 oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_ERROR, gaim_parse_msgerr, 0); |
|
| 1157 oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_MTN, gaim_parse_mtn, 0); |
|
| 1158 oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_ACK, gaim_parse_msgack, 0); |
|
| 1159 oscar_data_addhandler(od, SNAC_FAMILY_ICQ, SNAC_SUBTYPE_ICQ_OFFLINEMSG, gaim_offlinemsg, 0); |
|
| 1160 oscar_data_addhandler(od, SNAC_FAMILY_ICQ, SNAC_SUBTYPE_ICQ_OFFLINEMSGCOMPLETE, gaim_offlinemsgdone, 0); |
|
| 1161 oscar_data_addhandler(od, SNAC_FAMILY_ICQ, SNAC_SUBTYPE_ICQ_ALIAS, gaim_icqalias, 0); |
|
| 1162 oscar_data_addhandler(od, SNAC_FAMILY_ICQ, SNAC_SUBTYPE_ICQ_INFO, gaim_icqinfo, 0); |
|
| 1163 oscar_data_addhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_RIGHTSINFO, gaim_parse_locaterights, 0); |
|
| 1164 oscar_data_addhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_USERINFO, gaim_parse_userinfo, 0); |
|
| 1165 oscar_data_addhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_ERROR, gaim_parse_locerr, 0); |
|
| 1166 oscar_data_addhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_GOTINFOBLOCK, gaim_got_infoblock, 0); |
|
| 1167 oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x0001, gaim_parse_genericerr, 0); |
|
| 1168 oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x000f, gaim_selfinfo, 0); |
|
| 1169 oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x001f, gaim_memrequest, 0); |
|
| 1170 oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x0021, oscar_icon_req,0); |
|
| 1171 oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_RATECHANGE, gaim_parse_ratechange, 0); |
|
| 1172 oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_REDIRECT, gaim_handle_redirect, 0); |
|
| 1173 oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_MOTD, gaim_parse_motd, 0); |
|
| 1174 oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_EVIL, gaim_parse_evilnotify, 0); |
|
| 1175 oscar_data_addhandler(od, SNAC_FAMILY_POPUP, 0x0002, gaim_popup, 0); |
|
| 1176 oscar_data_addhandler(od, SNAC_FAMILY_USERLOOKUP, SNAC_SUBTYPE_USERLOOKUP_ERROR, gaim_parse_searcherror, 0); |
|
| 1177 oscar_data_addhandler(od, SNAC_FAMILY_USERLOOKUP, 0x0003, gaim_parse_searchreply, 0); |
|
| 1178 |
|
| 1179 gaim_debug_misc("oscar", "oscar_login: gc = %p\n", gc); |
|
| 1180 |
|
| 1181 if (!aim_snvalid(gaim_account_get_username(account))) { |
|
| 1182 gchar *buf; |
|
| 1183 buf = g_strdup_printf(_("Unable to login: Could not sign on as %s because the screen name is invalid. Screen names must either start with a letter and contain only letters, numbers and spaces, or contain only numbers."), gaim_account_get_username(account)); |
|
| 1184 gc->wants_to_die = TRUE; |
|
| 1185 gaim_connection_error(gc, buf); |
|
| 1186 g_free(buf); |
|
| 1187 } |
|
| 1188 |
|
| 1189 if (aim_sn_is_icq((gaim_account_get_username(account)))) { |
|
| 1190 od->icq = TRUE; |
|
| 1191 } else { |
|
| 1192 gc->flags |= GAIM_CONNECTION_HTML; |
|
| 1193 gc->flags |= GAIM_CONNECTION_AUTO_RESP; |
|
| 1194 } |
|
| 1195 |
|
| 1196 /* Connect to core Gaim signals */ |
|
| 1197 gaim_prefs_connect_callback(gc, "/plugins/prpl/oscar/recent_buddies", recent_buddies_cb, gc); |
|
| 1198 |
|
| 1199 newconn = flap_connection_new(od, SNAC_FAMILY_AUTH); |
|
| 1200 newconn->connect_info = gaim_proxy_connect(account, |
|
| 1201 gaim_account_get_string(account, "server", OSCAR_DEFAULT_LOGIN_SERVER), |
|
| 1202 gaim_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT), |
|
| 1203 connection_established_cb, newconn); |
|
| 1204 if (newconn->connect_info == NULL) |
|
| 1205 { |
|
| 1206 gaim_connection_error(gc, _("Couldn't connect to host")); |
|
| 1207 return; |
|
| 1208 } |
|
| 1209 |
|
| 1210 gaim_connection_update_progress(gc, _("Connecting"), 0, OSCAR_CONNECT_STEPS); |
|
| 1211 ck[0] = 0x5a; |
|
| 1212 } |
|
| 1213 |
|
| 1214 static void |
|
| 1215 oscar_close(GaimConnection *gc) |
|
| 1216 { |
|
| 1217 OscarData *od; |
|
| 1218 |
|
| 1219 od = (OscarData *)gc->proto_data; |
|
| 1220 |
|
| 1221 while (od->oscar_chats) |
|
| 1222 { |
|
| 1223 struct chat_connection *cc = od->oscar_chats->data; |
|
| 1224 od->oscar_chats = g_slist_remove(od->oscar_chats, cc); |
|
| 1225 oscar_chat_destroy(cc); |
|
| 1226 } |
|
| 1227 while (od->create_rooms) |
|
| 1228 { |
|
| 1229 struct create_room *cr = od->create_rooms->data; |
|
| 1230 g_free(cr->name); |
|
| 1231 od->create_rooms = g_slist_remove(od->create_rooms, cr); |
|
| 1232 g_free(cr); |
|
| 1233 } |
|
| 1234 oscar_data_destroy(od); |
|
| 1235 gc->proto_data = NULL; |
|
| 1236 |
|
| 1237 gaim_prefs_disconnect_by_handle(gc); |
|
| 1238 |
|
| 1239 gaim_debug_info("oscar", "Signed off.\n"); |
|
| 1240 } |
|
| 1241 |
|
| 1242 static int |
|
| 1243 gaim_parse_auth_resp(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) |
|
| 1244 { |
|
| 1245 GaimConnection *gc = od->gc; |
|
| 1246 GaimAccount *account = gc->account; |
|
| 1247 char *host; int port; |
|
| 1248 int i; |
|
| 1249 FlapConnection *newconn; |
|
| 1250 va_list ap; |
|
| 1251 struct aim_authresp_info *info; |
|
| 1252 |
|
| 1253 port = gaim_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT); |
|
| 1254 |
|
| 1255 va_start(ap, fr); |
|
| 1256 info = va_arg(ap, struct aim_authresp_info *); |
|
| 1257 va_end(ap); |
|
| 1258 |
|
| 1259 gaim_debug_info("oscar", |
|
| 1260 "inside auth_resp (Screen name: %s)\n", info->sn); |
|
| 1261 |
|
| 1262 if (info->errorcode || !info->bosip || !info->cookielen || !info->cookie) { |
|
| 1263 char buf[256]; |
|
| 1264 switch (info->errorcode) { |
|
| 1265 case 0x05: |
|
| 1266 /* Incorrect nick/password */ |
|
| 1267 gc->wants_to_die = TRUE; |
|
| 1268 gaim_connection_error(gc, _("Incorrect nickname or password.")); |
|
| 1269 break; |
|
| 1270 case 0x11: |
|
| 1271 /* Suspended account */ |
|
| 1272 gc->wants_to_die = TRUE; |
|
| 1273 gaim_connection_error(gc, _("Your account is currently suspended.")); |
|
| 1274 break; |
|
| 1275 case 0x14: |
|
| 1276 /* service temporarily unavailable */ |
|
| 1277 gaim_connection_error(gc, _("The AOL Instant Messenger service is temporarily unavailable.")); |
|
| 1278 break; |
|
| 1279 case 0x18: |
|
| 1280 /* connecting too frequently */ |
|
| 1281 gc->wants_to_die = TRUE; |
|
| 1282 gaim_connection_error(gc, _("You have been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer.")); |
|
| 1283 break; |
|
| 1284 case 0x1c: |
|
| 1285 /* client too old */ |
|
| 1286 gc->wants_to_die = TRUE; |
|
| 1287 g_snprintf(buf, sizeof(buf), _("The client version you are using is too old. Please upgrade at %s"), GAIM_WEBSITE); |
|
| 1288 gaim_connection_error(gc, buf); |
|
| 1289 break; |
|
| 1290 default: |
|
| 1291 gaim_connection_error(gc, _("Authentication failed")); |
|
| 1292 break; |
|
| 1293 } |
|
| 1294 gaim_debug_error("oscar", "Login Error Code 0x%04hx\n", info->errorcode); |
|
| 1295 gaim_debug_error("oscar", "Error URL: %s\n", info->errorurl); |
|
| 1296 od->killme = TRUE; |
|
| 1297 return 1; |
|
| 1298 } |
|
| 1299 |
|
| 1300 gaim_debug_misc("oscar", "Reg status: %hu\n", info->regstatus); |
|
| 1301 gaim_debug_misc("oscar", "E-mail: %s\n", |
|
| 1302 (info->email != NULL) ? info->email : "null"); |
|
| 1303 gaim_debug_misc("oscar", "BOSIP: %s\n", info->bosip); |
|
| 1304 gaim_debug_info("oscar", "Closing auth connection...\n"); |
|
| 1305 flap_connection_schedule_destroy(conn, OSCAR_DISCONNECT_DONE); |
|
| 1306 |
|
| 1307 for (i = 0; i < strlen(info->bosip); i++) { |
|
| 1308 if (info->bosip[i] == ':') { |
|
| 1309 port = atoi(&(info->bosip[i+1])); |
|
| 1310 break; |
|
| 1311 } |
|
| 1312 } |
|
| 1313 host = g_strndup(info->bosip, i); |
|
| 1314 newconn = flap_connection_new(od, SNAC_FAMILY_LOCATE); |
|
| 1315 newconn->cookielen = info->cookielen; |
|
| 1316 newconn->cookie = g_memdup(info->cookie, info->cookielen); |
|
| 1317 newconn->connect_info = gaim_proxy_connect(account, host, port, |
|
| 1318 connection_established_cb, newconn); |
|
| 1319 g_free(host); |
|
| 1320 if (newconn->connect_info == NULL) |
|
| 1321 { |
|
| 1322 gaim_connection_error(gc, _("Could Not Connect")); |
|
| 1323 od->killme = TRUE; |
|
| 1324 return 0; |
|
| 1325 } |
|
| 1326 |
|
| 1327 gaim_connection_update_progress(gc, _("Received authorization"), 3, OSCAR_CONNECT_STEPS); |
|
| 1328 ck[3] = 0x64; |
|
| 1329 |
|
| 1330 return 1; |
|
| 1331 } |
|
| 1332 |
|
| 1333 static void |
|
| 1334 gaim_parse_auth_securid_request_yes_cb(gpointer user_data, const char *msg) |
|
| 1335 { |
|
| 1336 GaimConnection *gc = user_data; |
|
| 1337 OscarData *od = gc->proto_data; |
|
| 1338 |
|
| 1339 aim_auth_securid_send(od, msg); |
|
| 1340 } |
|
| 1341 |
|
| 1342 static void |
|
| 1343 gaim_parse_auth_securid_request_no_cb(gpointer user_data, const char *value) |
|
| 1344 { |
|
| 1345 GaimConnection *gc = user_data; |
|
| 1346 OscarData *od = gc->proto_data; |
|
| 1347 |
|
| 1348 /* Disconnect */ |
|
| 1349 gc->wants_to_die = TRUE; |
|
| 1350 gaim_connection_error(gc, _("The SecurID key entered is invalid.")); |
|
| 1351 od->killme = TRUE; |
|
| 1352 } |
|
| 1353 |
|
| 1354 static int |
|
| 1355 gaim_parse_auth_securid_request(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) |
|
| 1356 { |
|
| 1357 GaimConnection *gc = od->gc; |
|
| 1358 GaimAccount *account = gaim_connection_get_account(gc); |
|
| 1359 gchar *primary; |
|
| 1360 |
|
| 1361 gaim_debug_info("oscar", "Got SecurID request\n"); |
|
| 1362 |
|
| 1363 primary = g_strdup_printf("Enter the SecurID key for %s.", gaim_account_get_username(account)); |
|
| 1364 gaim_request_input(gc, NULL, _("Enter SecurID"), primary, |
|
| 1365 _("Enter the 6 digit number from the digital display."), |
|
| 1366 FALSE, FALSE, NULL, |
|
| 1367 _("OK"), G_CALLBACK(gaim_parse_auth_securid_request_yes_cb), |
|
| 1368 _("Cancel"), G_CALLBACK(gaim_parse_auth_securid_request_no_cb), |
|
| 1369 gc); |
|
| 1370 g_free(primary); |
|
| 1371 |
|
| 1372 return 1; |
|
| 1373 } |
|
| 1374 |
|
| 1375 /* XXX - Should use gaim_url_fetch for the below stuff */ |
|
| 1376 struct pieceofcrap { |
|
| 1377 GaimConnection *gc; |
|
| 1378 unsigned long offset; |
|
| 1379 unsigned long len; |
|
| 1380 char *modname; |
|
| 1381 int fd; |
|
| 1382 FlapConnection *conn; |
|
| 1383 unsigned int inpa; |
|
| 1384 }; |
|
| 1385 |
|
| 1386 static void damn_you(gpointer data, gint source, GaimInputCondition c) |
|
| 1387 { |
|
| 1388 struct pieceofcrap *pos = data; |
|
| 1389 OscarData *od = pos->gc->proto_data; |
|
| 1390 char in = '\0'; |
|
| 1391 int x = 0; |
|
| 1392 unsigned char m[17]; |
|
| 1393 |
|
| 1394 while (read(pos->fd, &in, 1) == 1) { |
|
| 1395 if (in == '\n') |
|
| 1396 x++; |
|
| 1397 else if (in != '\r') |
|
| 1398 x = 0; |
|
| 1399 if (x == 2) |
|
| 1400 break; |
|
| 1401 in = '\0'; |
|
| 1402 } |
|
| 1403 if (in != '\n') { |
|
| 1404 char buf[256]; |
|
| 1405 g_snprintf(buf, sizeof(buf), _("You may be disconnected shortly. You may want to use TOC until " |
|
| 1406 "this is fixed. Check %s for updates."), GAIM_WEBSITE); |
|
| 1407 gaim_notify_warning(pos->gc, NULL, |
|
| 1408 _("Gaim was unable to get a valid AIM login hash."), |
|
| 1409 buf); |
|
| 1410 gaim_input_remove(pos->inpa); |
|
| 1411 close(pos->fd); |
|
| 1412 g_free(pos); |
|
| 1413 return; |
|
| 1414 } |
|
| 1415 if (read(pos->fd, m, 16) != 16) |
|
| 1416 { |
|
| 1417 gaim_debug_warning("oscar", "Could not read full AIM login hash " |
|
| 1418 "from " AIMHASHDATA "--that's bad.\n"); |
|
| 1419 } |
|
| 1420 m[16] = '\0'; |
|
| 1421 gaim_debug_misc("oscar", "Sending hash: "); |
|
| 1422 for (x = 0; x < 16; x++) |
|
| 1423 gaim_debug_misc(NULL, "%02hhx ", (unsigned char)m[x]); |
|
| 1424 |
|
| 1425 gaim_debug_misc(NULL, "\n"); |
|
| 1426 gaim_input_remove(pos->inpa); |
|
| 1427 close(pos->fd); |
|
| 1428 aim_sendmemblock(od, pos->conn, 0, 16, m, AIM_SENDMEMBLOCK_FLAG_ISHASH); |
|
| 1429 g_free(pos); |
|
| 1430 } |
|
| 1431 |
|
| 1432 static void |
|
| 1433 straight_to_hell(gpointer data, gint source, const gchar *error_message) |
|
| 1434 { |
|
| 1435 struct pieceofcrap *pos = data; |
|
| 1436 gchar *buf; |
|
| 1437 |
|
| 1438 if (!GAIM_CONNECTION_IS_VALID(pos->gc)) |
|
| 1439 { |
|
| 1440 g_free(pos->modname); |
|
| 1441 g_free(pos); |
|
| 1442 return; |
|
| 1443 } |
|
| 1444 |
|
| 1445 pos->fd = source; |
|
| 1446 |
|
| 1447 if (source < 0) { |
|
| 1448 buf = g_strdup_printf(_("You may be disconnected shortly. You may want to use TOC until " |
|
| 1449 "this is fixed. Check %s for updates."), GAIM_WEBSITE); |
|
| 1450 gaim_notify_warning(pos->gc, NULL, |
|
| 1451 _("Gaim was unable to get a valid AIM login hash."), |
|
| 1452 buf); |
|
| 1453 g_free(buf); |
|
| 1454 g_free(pos->modname); |
|
| 1455 g_free(pos); |
|
| 1456 return; |
|
| 1457 } |
|
| 1458 |
|
| 1459 buf = g_strdup_printf("GET " AIMHASHDATA "?offset=%ld&len=%ld&modname=%s HTTP/1.0\n\n", |
|
| 1460 pos->offset, pos->len, pos->modname ? pos->modname : ""); |
|
| 1461 write(pos->fd, buf, strlen(buf)); |
|
| 1462 g_free(buf); |
|
| 1463 g_free(pos->modname); |
|
| 1464 pos->inpa = gaim_input_add(pos->fd, GAIM_INPUT_READ, damn_you, pos); |
|
| 1465 return; |
|
| 1466 } |
|
| 1467 |
|
| 1468 /* size of icbmui.ocm, the largest module in AIM 3.5 */ |
|
| 1469 #define AIM_MAX_FILE_SIZE 98304 |
|
| 1470 |
|
| 1471 int gaim_memrequest(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 1472 va_list ap; |
|
| 1473 struct pieceofcrap *pos; |
|
| 1474 guint32 offset, len; |
|
| 1475 char *modname; |
|
| 1476 |
|
| 1477 va_start(ap, fr); |
|
| 1478 offset = va_arg(ap, guint32); |
|
| 1479 len = va_arg(ap, guint32); |
|
| 1480 modname = va_arg(ap, char *); |
|
| 1481 va_end(ap); |
|
| 1482 |
|
| 1483 gaim_debug_misc("oscar", "offset: %u, len: %u, file: %s\n", |
|
| 1484 offset, len, (modname ? modname : "aim.exe")); |
|
| 1485 |
|
| 1486 if (len == 0) { |
|
| 1487 gaim_debug_misc("oscar", "len is 0, hashing NULL\n"); |
|
| 1488 aim_sendmemblock(od, conn, offset, len, NULL, |
|
| 1489 AIM_SENDMEMBLOCK_FLAG_ISREQUEST); |
|
| 1490 return 1; |
|
| 1491 } |
|
| 1492 /* uncomment this when you're convinced it's right. remember, it's been wrong before. */ |
|
| 1493 #if 0 |
|
| 1494 if (offset > AIM_MAX_FILE_SIZE || len > AIM_MAX_FILE_SIZE) { |
|
| 1495 char *buf; |
|
| 1496 int i = 8; |
|
| 1497 if (modname) |
|
| 1498 i += strlen(modname); |
|
| 1499 buf = g_malloc(i); |
|
| 1500 i = 0; |
|
| 1501 if (modname) { |
|
| 1502 memcpy(buf, modname, strlen(modname)); |
|
| 1503 i += strlen(modname); |
|
| 1504 } |
|
| 1505 buf[i++] = offset & 0xff; |
|
| 1506 buf[i++] = (offset >> 8) & 0xff; |
|
| 1507 buf[i++] = (offset >> 16) & 0xff; |
|
| 1508 buf[i++] = (offset >> 24) & 0xff; |
|
| 1509 buf[i++] = len & 0xff; |
|
| 1510 buf[i++] = (len >> 8) & 0xff; |
|
| 1511 buf[i++] = (len >> 16) & 0xff; |
|
| 1512 buf[i++] = (len >> 24) & 0xff; |
|
| 1513 gaim_debug_misc("oscar", "len + offset is invalid, " |
|
| 1514 "hashing request\n"); |
|
| 1515 aim_sendmemblock(od, command->conn, offset, i, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST); |
|
| 1516 g_free(buf); |
|
| 1517 return 1; |
|
| 1518 } |
|
| 1519 #endif |
|
| 1520 |
|
| 1521 pos = g_new0(struct pieceofcrap, 1); |
|
| 1522 pos->gc = od->gc; |
|
| 1523 pos->conn = conn; |
|
| 1524 |
|
| 1525 pos->offset = offset; |
|
| 1526 pos->len = len; |
|
| 1527 pos->modname = g_strdup(modname); |
|
| 1528 |
|
| 1529 /* TODO: Keep track of this return value. */ |
|
| 1530 if (gaim_proxy_connect(pos->gc->account, "gaim.sourceforge.net", 80, |
|
| 1531 straight_to_hell, pos) == NULL) |
|
| 1532 { |
|
| 1533 char buf[256]; |
|
| 1534 if (pos->modname) |
|
| 1535 g_free(pos->modname); |
|
| 1536 g_free(pos); |
|
| 1537 g_snprintf(buf, sizeof(buf), _("You may be disconnected shortly. " |
|
| 1538 "Check %s for updates."), GAIM_WEBSITE); |
|
| 1539 gaim_notify_warning(pos->gc, NULL, |
|
| 1540 _("Gaim was unable to get a valid login hash."), |
|
| 1541 buf); |
|
| 1542 } |
|
| 1543 |
|
| 1544 return 1; |
|
| 1545 } |
|
| 1546 |
|
| 1547 static int |
|
| 1548 gaim_parse_login(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) |
|
| 1549 { |
|
| 1550 GaimConnection *gc; |
|
| 1551 GaimAccount *account; |
|
| 1552 ClientInfo info = CLIENTINFO_GAIM; |
|
| 1553 va_list ap; |
|
| 1554 char *key; |
|
| 1555 |
|
| 1556 gc = od->gc; |
|
| 1557 account = gaim_connection_get_account(gc); |
|
| 1558 |
|
| 1559 va_start(ap, fr); |
|
| 1560 key = va_arg(ap, char *); |
|
| 1561 va_end(ap); |
|
| 1562 |
|
| 1563 aim_send_login(od, conn, gaim_account_get_username(account), |
|
| 1564 gaim_connection_get_password(gc), &info, key); |
|
| 1565 |
|
| 1566 gaim_connection_update_progress(gc, _("Password sent"), 2, OSCAR_CONNECT_STEPS); |
|
| 1567 ck[2] = 0x6c; |
|
| 1568 |
|
| 1569 return 1; |
|
| 1570 } |
|
| 1571 |
|
| 1572 static int |
|
| 1573 gaim_handle_redirect(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) |
|
| 1574 { |
|
| 1575 GaimConnection *gc = od->gc; |
|
| 1576 GaimAccount *account = gaim_connection_get_account(gc); |
|
| 1577 char *host, *separator; |
|
| 1578 int port; |
|
| 1579 FlapConnection *newconn; |
|
| 1580 va_list ap; |
|
| 1581 struct aim_redirect_data *redir; |
|
| 1582 |
|
| 1583 va_start(ap, fr); |
|
| 1584 redir = va_arg(ap, struct aim_redirect_data *); |
|
| 1585 va_end(ap); |
|
| 1586 |
|
| 1587 port = gaim_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT); |
|
| 1588 separator = strchr(redir->ip, ':'); |
|
| 1589 if (separator != NULL) |
|
| 1590 { |
|
| 1591 host = g_strndup(redir->ip, separator - redir->ip); |
|
| 1592 port = atoi(separator + 1); |
|
| 1593 } |
|
| 1594 else |
|
| 1595 host = g_strdup(redir->ip); |
|
| 1596 |
|
| 1597 gaim_debug_info("oscar", "Connecting to FLAP server %s:%d of type 0x%04hx\n", |
|
| 1598 host, port, redir->group); |
|
| 1599 newconn = flap_connection_new(od, redir->group); |
|
| 1600 newconn->cookielen = redir->cookielen; |
|
| 1601 newconn->cookie = g_memdup(redir->cookie, redir->cookielen); |
|
| 1602 if (newconn->type == SNAC_FAMILY_CHAT) |
|
| 1603 { |
|
| 1604 struct chat_connection *cc; |
|
| 1605 cc = g_new0(struct chat_connection, 1); |
|
| 1606 cc->conn = newconn; |
|
| 1607 cc->gc = gc; |
|
| 1608 cc->name = g_strdup(redir->chat.room); |
|
| 1609 cc->exchange = redir->chat.exchange; |
|
| 1610 cc->instance = redir->chat.instance; |
|
| 1611 cc->show = extract_name(redir->chat.room); |
|
| 1612 newconn->connect_data = cc; |
|
| 1613 gaim_debug_info("oscar", "Connecting to chat room %s exchange %hu\n", cc->name, cc->exchange); |
|
| 1614 } |
|
| 1615 |
|
| 1616 newconn->connect_info = gaim_proxy_connect(account, host, port, |
|
| 1617 connection_established_cb, newconn); |
|
| 1618 if (newconn->connect_info == NULL) |
|
| 1619 { |
|
| 1620 flap_connection_schedule_destroy(newconn, OSCAR_DISCONNECT_COULD_NOT_CONNECT); |
|
| 1621 gaim_debug_error("oscar", "Unable to connect to FLAP server " |
|
| 1622 "of type 0x%04hx\n", redir->group); |
|
| 1623 } |
|
| 1624 g_free(host); |
|
| 1625 |
|
| 1626 return 1; |
|
| 1627 } |
|
| 1628 |
|
| 1629 static int gaim_parse_oncoming(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) |
|
| 1630 { |
|
| 1631 GaimConnection *gc; |
|
| 1632 GaimAccount *account; |
|
| 1633 GaimPresence *presence; |
|
| 1634 struct buddyinfo *bi; |
|
| 1635 time_t time_idle = 0, signon = 0; |
|
| 1636 int type = 0; |
|
| 1637 gboolean buddy_is_away = FALSE; |
|
| 1638 const char *status_id; |
|
| 1639 gboolean have_status_message = FALSE; |
|
| 1640 char *message = NULL; |
|
| 1641 va_list ap; |
|
| 1642 aim_userinfo_t *info; |
|
| 1643 |
|
| 1644 gc = od->gc; |
|
| 1645 account = gaim_connection_get_account(gc); |
|
| 1646 presence = gaim_account_get_presence(account); |
|
| 1647 |
|
| 1648 va_start(ap, fr); |
|
| 1649 info = va_arg(ap, aim_userinfo_t *); |
|
| 1650 va_end(ap); |
|
| 1651 |
|
| 1652 g_return_val_if_fail(info != NULL, 1); |
|
| 1653 g_return_val_if_fail(info->sn != NULL, 1); |
|
| 1654 |
|
| 1655 if (info->present & AIM_USERINFO_PRESENT_FLAGS) { |
|
| 1656 if (info->flags & AIM_FLAG_AWAY) |
|
| 1657 buddy_is_away = TRUE; |
|
| 1658 } |
|
| 1659 if (info->present & AIM_USERINFO_PRESENT_ICQEXTSTATUS) { |
|
| 1660 type = info->icqinfo.status; |
|
| 1661 if (!(info->icqinfo.status & AIM_ICQ_STATE_CHAT) && |
|
| 1662 (info->icqinfo.status != AIM_ICQ_STATE_NORMAL)) { |
|
| 1663 buddy_is_away = TRUE; |
|
| 1664 } |
|
| 1665 } |
|
| 1666 |
|
| 1667 if (aim_sn_is_icq(info->sn)) { |
|
| 1668 if (type & AIM_ICQ_STATE_CHAT) |
|
| 1669 status_id = OSCAR_STATUS_ID_FREE4CHAT; |
|
| 1670 else if (type & AIM_ICQ_STATE_DND) |
|
| 1671 status_id = OSCAR_STATUS_ID_DND; |
|
| 1672 else if (type & AIM_ICQ_STATE_OUT) |
|
| 1673 status_id = OSCAR_STATUS_ID_NA; |
|
| 1674 else if (type & AIM_ICQ_STATE_BUSY) |
|
| 1675 status_id = OSCAR_STATUS_ID_OCCUPIED; |
|
| 1676 else if (type & AIM_ICQ_STATE_AWAY) |
|
| 1677 status_id = OSCAR_STATUS_ID_AWAY; |
|
| 1678 else if (type & AIM_ICQ_STATE_INVISIBLE) |
|
| 1679 status_id = OSCAR_STATUS_ID_INVISIBLE; |
|
| 1680 else |
|
| 1681 status_id = OSCAR_STATUS_ID_AVAILABLE; |
|
| 1682 } else { |
|
| 1683 if (buddy_is_away) |
|
| 1684 status_id = OSCAR_STATUS_ID_AWAY; |
|
| 1685 else |
|
| 1686 status_id = OSCAR_STATUS_ID_AVAILABLE; |
|
| 1687 } |
|
| 1688 |
|
| 1689 /* |
|
| 1690 * Handle the available message. If info->status is NULL then the user |
|
| 1691 * may or may not have an available message, so don't do anything. If |
|
| 1692 * info->status is set to the empty string, then the user's client DOES |
|
| 1693 * support available messages and the user DOES NOT have one set. |
|
| 1694 * Otherwise info->status contains the available message. |
|
| 1695 */ |
|
| 1696 if (info->status != NULL) |
|
| 1697 { |
|
| 1698 have_status_message = TRUE; |
|
| 1699 if (info->status[0] != '\0') |
|
| 1700 message = oscar_encoding_to_utf8(info->status_encoding, |
|
| 1701 info->status, info->status_len); |
|
| 1702 } |
|
| 1703 |
|
| 1704 if (have_status_message) |
|
| 1705 { |
|
| 1706 gaim_prpl_got_user_status(account, info->sn, status_id, |
|
| 1707 "message", message, NULL); |
|
| 1708 g_free(message); |
|
| 1709 } |
|
| 1710 else |
|
| 1711 gaim_prpl_got_user_status(account, info->sn, status_id, NULL); |
|
| 1712 |
|
| 1713 /* Login time stuff */ |
|
| 1714 if (info->present & AIM_USERINFO_PRESENT_ONLINESINCE) |
|
| 1715 signon = info->onlinesince; |
|
| 1716 else if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN) |
|
| 1717 signon = time(NULL) - info->sessionlen; |
|
| 1718 if (!aim_sncmp(gaim_account_get_username(account), info->sn)) { |
|
| 1719 gaim_connection_set_display_name(gc, info->sn); |
|
| 1720 od->timeoffset = signon - gaim_presence_get_login_time(presence); |
|
| 1721 } |
|
| 1722 gaim_prpl_got_user_login_time(account, info->sn, signon - od->timeoffset); |
|
| 1723 |
|
| 1724 /* Idle time stuff */ |
|
| 1725 /* info->idletime is the number of minutes that this user has been idle */ |
|
| 1726 if (info->present & AIM_USERINFO_PRESENT_IDLE) |
|
| 1727 time_idle = time(NULL) - info->idletime * 60; |
|
| 1728 |
|
| 1729 if (time_idle > 0) |
|
| 1730 gaim_prpl_got_user_idle(account, info->sn, TRUE, time_idle); |
|
| 1731 else |
|
| 1732 gaim_prpl_got_user_idle(account, info->sn, FALSE, 0); |
|
| 1733 |
|
| 1734 /* Server stored icon stuff */ |
|
| 1735 bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(account, info->sn)); |
|
| 1736 if (!bi) { |
|
| 1737 bi = g_new0(struct buddyinfo, 1); |
|
| 1738 g_hash_table_insert(od->buddyinfo, g_strdup(gaim_normalize(account, info->sn)), bi); |
|
| 1739 } |
|
| 1740 bi->typingnot = FALSE; |
|
| 1741 bi->ico_informed = FALSE; |
|
| 1742 bi->ipaddr = info->icqinfo.ipaddr; |
|
| 1743 |
|
| 1744 if (info->iconcsumlen) { |
|
| 1745 const char *filename, *saved_b16 = NULL; |
|
| 1746 char *b16 = NULL, *filepath = NULL; |
|
| 1747 GaimBuddy *b = NULL; |
|
| 1748 |
|
| 1749 b16 = gaim_base16_encode(info->iconcsum, info->iconcsumlen); |
|
| 1750 b = gaim_find_buddy(account, info->sn); |
|
| 1751 /* |
|
| 1752 * If for some reason the checksum is valid, but cached file is not.. |
|
| 1753 * we want to know. |
|
| 1754 */ |
|
| 1755 if (b != NULL) |
|
| 1756 filename = gaim_blist_node_get_string((GaimBlistNode*)b, "buddy_icon"); |
|
| 1757 else |
|
| 1758 filename = NULL; |
|
| 1759 if (filename != NULL) { |
|
| 1760 if (g_file_test(filename, G_FILE_TEST_EXISTS)) |
|
| 1761 saved_b16 = gaim_blist_node_get_string((GaimBlistNode*)b, |
|
| 1762 "icon_checksum"); |
|
| 1763 else { |
|
| 1764 filepath = g_build_filename(gaim_buddy_icons_get_cache_dir(), |
|
| 1765 filename, NULL); |
|
| 1766 if (g_file_test(filepath, G_FILE_TEST_EXISTS)) |
|
| 1767 saved_b16 = gaim_blist_node_get_string((GaimBlistNode*)b, |
|
| 1768 "icon_checksum"); |
|
| 1769 g_free(filepath); |
|
| 1770 } |
|
| 1771 } else |
|
| 1772 saved_b16 = NULL; |
|
| 1773 |
|
| 1774 if (!b16 || !saved_b16 || strcmp(b16, saved_b16)) { |
|
| 1775 GSList *cur = od->requesticon; |
|
| 1776 while (cur && aim_sncmp((char *)cur->data, info->sn)) |
|
| 1777 cur = cur->next; |
|
| 1778 if (!cur) { |
|
| 1779 od->requesticon = g_slist_append(od->requesticon, g_strdup(gaim_normalize(account, info->sn))); |
|
| 1780 if (od->icontimer == 0) |
|
| 1781 od->icontimer = gaim_timeout_add(500, gaim_icon_timerfunc, gc); |
|
| 1782 } |
|
| 1783 } |
|
| 1784 g_free(b16); |
|
| 1785 } |
|
| 1786 |
|
| 1787 return 1; |
|
| 1788 } |
|
| 1789 |
|
| 1790 static void gaim_check_comment(OscarData *od, const char *str) { |
|
| 1791 if ((str == NULL) || strcmp(str, (const char *)ck)) |
|
| 1792 aim_locate_setcaps(od, caps_aim); |
|
| 1793 else |
|
| 1794 aim_locate_setcaps(od, caps_aim | OSCAR_CAPABILITY_SECUREIM); |
|
| 1795 } |
|
| 1796 |
|
| 1797 static int gaim_parse_offgoing(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 1798 GaimConnection *gc = od->gc; |
|
| 1799 GaimAccount *account = gaim_connection_get_account(gc); |
|
| 1800 va_list ap; |
|
| 1801 aim_userinfo_t *info; |
|
| 1802 |
|
| 1803 va_start(ap, fr); |
|
| 1804 info = va_arg(ap, aim_userinfo_t *); |
|
| 1805 va_end(ap); |
|
| 1806 |
|
| 1807 gaim_prpl_got_user_status(account, info->sn, OSCAR_STATUS_ID_OFFLINE, NULL); |
|
| 1808 |
|
| 1809 g_hash_table_remove(od->buddyinfo, gaim_normalize(gc->account, info->sn)); |
|
| 1810 |
|
| 1811 return 1; |
|
| 1812 } |
|
| 1813 |
|
| 1814 static int incomingim_chan1(OscarData *od, FlapConnection *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args) { |
|
| 1815 GaimConnection *gc = od->gc; |
|
| 1816 GaimAccount *account = gaim_connection_get_account(gc); |
|
| 1817 GaimMessageFlags flags = 0; |
|
| 1818 struct buddyinfo *bi; |
|
| 1819 char *iconfile; |
|
| 1820 GString *message; |
|
| 1821 gchar *tmp; |
|
| 1822 aim_mpmsg_section_t *curpart; |
|
| 1823 const char *start, *end; |
|
| 1824 GData *attribs; |
|
| 1825 |
|
| 1826 gaim_debug_misc("oscar", "Received IM from %s with %d parts\n", |
|
| 1827 userinfo->sn, args->mpmsg.numparts); |
|
| 1828 |
|
| 1829 if (args->mpmsg.numparts == 0) |
|
| 1830 return 1; |
|
| 1831 |
|
| 1832 bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(account, userinfo->sn)); |
|
| 1833 if (!bi) { |
|
| 1834 bi = g_new0(struct buddyinfo, 1); |
|
| 1835 g_hash_table_insert(od->buddyinfo, g_strdup(gaim_normalize(account, userinfo->sn)), bi); |
|
| 1836 } |
|
| 1837 |
|
| 1838 if (args->icbmflags & AIM_IMFLAGS_AWAY) |
|
| 1839 flags |= GAIM_MESSAGE_AUTO_RESP; |
|
| 1840 |
|
| 1841 if (args->icbmflags & AIM_IMFLAGS_TYPINGNOT) |
|
| 1842 bi->typingnot = TRUE; |
|
| 1843 else |
|
| 1844 bi->typingnot = FALSE; |
|
| 1845 |
|
| 1846 if ((args->icbmflags & AIM_IMFLAGS_HASICON) && (args->iconlen) && (args->iconsum) && (args->iconstamp)) { |
|
| 1847 gaim_debug_misc("oscar", "%s has an icon\n", userinfo->sn); |
|
| 1848 if ((args->iconlen != bi->ico_len) || (args->iconsum != bi->ico_csum) || (args->iconstamp != bi->ico_time)) { |
|
| 1849 bi->ico_need = TRUE; |
|
| 1850 bi->ico_len = args->iconlen; |
|
| 1851 bi->ico_csum = args->iconsum; |
|
| 1852 bi->ico_time = args->iconstamp; |
|
| 1853 } |
|
| 1854 } |
|
| 1855 |
|
| 1856 iconfile = gaim_buddy_icons_get_full_path(gaim_account_get_buddy_icon(account)); |
|
| 1857 if ((iconfile != NULL) && |
|
| 1858 (args->icbmflags & AIM_IMFLAGS_BUDDYREQ) && !bi->ico_sent && bi->ico_informed) { |
|
| 1859 FILE *file; |
|
| 1860 struct stat st; |
|
| 1861 |
|
| 1862 if (!g_stat(iconfile, &st)) { |
|
| 1863 guchar *buf = g_malloc(st.st_size); |
|
| 1864 file = g_fopen(iconfile, "rb"); |
|
| 1865 if (file) { |
|
| 1866 /* XXX - Use g_file_get_contents() */ |
|
| 1867 /* g_file_get_contents(iconfile, &data, &len, NULL); */ |
|
| 1868 int len = fread(buf, 1, st.st_size, file); |
|
| 1869 gaim_debug_info("oscar", |
|
| 1870 "Sending buddy icon to %s (%d bytes, " |
|
| 1871 "%lu reported)\n", |
|
| 1872 userinfo->sn, len, st.st_size); |
|
| 1873 aim_im_sendch2_icon(od, userinfo->sn, buf, st.st_size, |
|
| 1874 st.st_mtime, aimutil_iconsum(buf, st.st_size)); |
|
| 1875 fclose(file); |
|
| 1876 } else |
|
| 1877 gaim_debug_error("oscar", "Can't open buddy icon file!\n"); |
|
| 1878 g_free(buf); |
|
| 1879 } else |
|
| 1880 gaim_debug_error("oscar", "Can't stat buddy icon file!\n"); |
|
| 1881 } |
|
| 1882 g_free(iconfile); |
|
| 1883 |
|
| 1884 message = g_string_new(""); |
|
| 1885 curpart = args->mpmsg.parts; |
|
| 1886 while (curpart != NULL) { |
|
| 1887 tmp = gaim_plugin_oscar_decode_im_part(account, userinfo->sn, curpart->charset, |
|
| 1888 curpart->charsubset, curpart->data, curpart->datalen); |
|
| 1889 if (tmp != NULL) { |
|
| 1890 g_string_append(message, tmp); |
|
| 1891 g_free(tmp); |
|
| 1892 } |
|
| 1893 |
|
| 1894 curpart = curpart->next; |
|
| 1895 } |
|
| 1896 tmp = g_string_free(message, FALSE); |
|
| 1897 |
|
| 1898 /* |
|
| 1899 * If the message is from an ICQ user and to an ICQ user then escape any HTML, |
|
| 1900 * because HTML is not sent over ICQ as a means to format a message. |
|
| 1901 * So any HTML we receive is intended to be displayed. Also, \r\n must be |
|
| 1902 * replaced with <br> |
|
| 1903 * |
|
| 1904 * Note: There *may* be some clients which send messages as HTML formatted - |
|
| 1905 * they need to be special-cased somehow. |
|
| 1906 */ |
|
| 1907 if (aim_sn_is_icq(gaim_account_get_username(account)) && aim_sn_is_icq(userinfo->sn)) { |
|
| 1908 /* being recevied by ICQ from ICQ - escape HTML so it is displayed as sent */ |
|
| 1909 gchar *tmp2 = g_markup_escape_text(tmp, -1); |
|
| 1910 g_free(tmp); |
|
| 1911 tmp = tmp2; |
|
| 1912 tmp2 = gaim_strreplace(tmp, "\r\n", "<br>"); |
|
| 1913 g_free(tmp); |
|
| 1914 tmp = tmp2; |
|
| 1915 } |
|
| 1916 |
|
| 1917 /* |
|
| 1918 * Convert iChat color tags to normal font tags. |
|
| 1919 */ |
|
| 1920 if (gaim_markup_find_tag("body", tmp, &start, &end, &attribs)) |
|
| 1921 { |
|
| 1922 const char *ichattextcolor, *ichatballooncolor; |
|
| 1923 |
|
| 1924 ichattextcolor = g_datalist_get_data(&attribs, "ichattextcolor"); |
|
| 1925 if (ichattextcolor != NULL) |
|
| 1926 { |
|
| 1927 gchar *tmp2; |
|
| 1928 tmp2 = g_strdup_printf("<font color=\"%s\">%s</font>", ichattextcolor, tmp); |
|
| 1929 g_free(tmp); |
|
| 1930 tmp = tmp2; |
|
| 1931 } |
|
| 1932 |
|
| 1933 ichatballooncolor = g_datalist_get_data(&attribs, "ichatballooncolor"); |
|
| 1934 if (ichatballooncolor != NULL) |
|
| 1935 { |
|
| 1936 gchar *tmp2; |
|
| 1937 tmp2 = g_strdup_printf("<font back=\"%s\">%s</font>", ichatballooncolor, tmp); |
|
| 1938 g_free(tmp); |
|
| 1939 tmp = tmp2; |
|
| 1940 } |
|
| 1941 |
|
| 1942 g_datalist_clear(&attribs); |
|
| 1943 } |
|
| 1944 |
|
| 1945 serv_got_im(gc, userinfo->sn, tmp, flags, time(NULL)); |
|
| 1946 g_free(tmp); |
|
| 1947 |
|
| 1948 return 1; |
|
| 1949 } |
|
| 1950 |
|
| 1951 static int |
|
| 1952 incomingim_chan2(OscarData *od, FlapConnection *conn, aim_userinfo_t *userinfo, IcbmArgsCh2 *args) |
|
| 1953 { |
|
| 1954 GaimConnection *gc; |
|
| 1955 GaimAccount *account; |
|
| 1956 char *message = NULL; |
|
| 1957 |
|
| 1958 g_return_val_if_fail(od != NULL, 0); |
|
| 1959 g_return_val_if_fail(od->gc != NULL, 0); |
|
| 1960 |
|
| 1961 gc = od->gc; |
|
| 1962 account = gaim_connection_get_account(gc); |
|
| 1963 od = gc->proto_data; |
|
| 1964 |
|
| 1965 if (args == NULL) |
|
| 1966 return 0; |
|
| 1967 |
|
| 1968 gaim_debug_misc("oscar", "Incoming rendezvous message of type %u, " |
|
| 1969 "user %s, status %hu\n", args->type, userinfo->sn, args->status); |
|
| 1970 |
|
| 1971 if (args->msg != NULL) |
|
| 1972 { |
|
| 1973 if (args->encoding != NULL) |
|
| 1974 { |
|
| 1975 char *encoding = NULL; |
|
| 1976 encoding = oscar_encoding_extract(args->encoding); |
|
| 1977 message = oscar_encoding_to_utf8(encoding, args->msg, args->msglen); |
|
| 1978 g_free(encoding); |
|
| 1979 } else { |
|
| 1980 if (g_utf8_validate(args->msg, args->msglen, NULL)) |
|
| 1981 message = g_strdup(args->msg); |
|
| 1982 } |
|
| 1983 } |
|
| 1984 |
|
| 1985 if (args->type & OSCAR_CAPABILITY_CHAT) |
|
| 1986 { |
|
| 1987 char *name; |
|
| 1988 GHashTable *components; |
|
| 1989 |
|
| 1990 if (!args->info.chat.roominfo.name || !args->info.chat.roominfo.exchange) { |
|
| 1991 g_free(message); |
|
| 1992 return 1; |
|
| 1993 } |
|
| 1994 components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, |
|
| 1995 g_free); |
|
| 1996 name = extract_name(args->info.chat.roominfo.name); |
|
| 1997 g_hash_table_replace(components, g_strdup("room"), |
|
| 1998 g_strdup(name ? name : args->info.chat.roominfo.name)); |
|
| 1999 g_hash_table_replace(components, g_strdup("exchange"), |
|
| 2000 g_strdup_printf("%d", args->info.chat.roominfo.exchange)); |
|
| 2001 serv_got_chat_invite(gc, |
|
| 2002 name ? name : args->info.chat.roominfo.name, |
|
| 2003 userinfo->sn, |
|
| 2004 message, |
|
| 2005 components); |
|
| 2006 if (name) |
|
| 2007 g_free(name); |
|
| 2008 } |
|
| 2009 |
|
| 2010 else if ((args->type & OSCAR_CAPABILITY_SENDFILE) || |
|
| 2011 (args->type & OSCAR_CAPABILITY_DIRECTIM)) |
|
| 2012 { |
|
| 2013 if (args->status == AIM_RENDEZVOUS_PROPOSE) |
|
| 2014 { |
|
| 2015 peer_connection_got_proposition(od, userinfo->sn, message, args); |
|
| 2016 } |
|
| 2017 else if (args->status == AIM_RENDEZVOUS_CANCEL) |
|
| 2018 { |
|
| 2019 /* The other user canceled a peer request */ |
|
| 2020 PeerConnection *conn; |
|
| 2021 |
|
| 2022 conn = peer_connection_find_by_cookie(od, userinfo->sn, args->cookie); |
|
| 2023 /* |
|
| 2024 * If conn is NULL it means we haven't tried to create |
|
| 2025 * a connection with that user. They may be trying to |
|
| 2026 * do something malicious. |
|
| 2027 */ |
|
| 2028 if (conn != NULL) |
|
| 2029 { |
|
| 2030 peer_connection_destroy(conn, OSCAR_DISCONNECT_REMOTE_CLOSED); |
|
| 2031 } |
|
| 2032 } |
|
| 2033 else if (args->status == AIM_RENDEZVOUS_CONNECTED) |
|
| 2034 { |
|
| 2035 /* Remote user has accepted our peer request */ |
|
| 2036 PeerConnection *conn; |
|
| 2037 |
|
| 2038 conn = peer_connection_find_by_cookie(od, userinfo->sn, args->cookie); |
|
| 2039 /* |
|
| 2040 * If conn is NULL it means we haven't tried to create |
|
| 2041 * a connection with that user. They may be trying to |
|
| 2042 * do something malicious. |
|
| 2043 */ |
|
| 2044 if (conn != NULL) |
|
| 2045 { |
|
| 2046 if (conn->listenerfd != -1) |
|
| 2047 { |
|
| 2048 /* |
|
| 2049 * If they are connecting directly to us then |
|
| 2050 * continue the peer negotiation by |
|
| 2051 * accepting connections on our listener port. |
|
| 2052 */ |
|
| 2053 conn->watcher_incoming = gaim_input_add(conn->listenerfd, |
|
| 2054 GAIM_INPUT_READ, peer_connection_listen_cb, conn); |
|
| 2055 } |
|
| 2056 } |
|
| 2057 } |
|
| 2058 } |
|
| 2059 |
|
| 2060 else if (args->type & OSCAR_CAPABILITY_GETFILE) |
|
| 2061 { |
|
| 2062 } |
|
| 2063 |
|
| 2064 else if (args->type & OSCAR_CAPABILITY_TALK) |
|
| 2065 { |
|
| 2066 } |
|
| 2067 |
|
| 2068 else if (args->type & OSCAR_CAPABILITY_BUDDYICON) |
|
| 2069 { |
|
| 2070 gaim_buddy_icons_set_for_user(account, userinfo->sn, |
|
| 2071 args->info.icon.icon, |
|
| 2072 args->info.icon.length); |
|
| 2073 } |
|
| 2074 |
|
| 2075 else if (args->type & OSCAR_CAPABILITY_ICQSERVERRELAY) |
|
| 2076 { |
|
| 2077 gaim_debug_error("oscar", "Got an ICQ Server Relay message of " |
|
| 2078 "type %d\n", args->info.rtfmsg.msgtype); |
|
| 2079 } |
|
| 2080 |
|
| 2081 else |
|
| 2082 { |
|
| 2083 gaim_debug_error("oscar", "Unknown request class %hu\n", |
|
| 2084 args->type); |
|
| 2085 } |
|
| 2086 |
|
| 2087 g_free(message); |
|
| 2088 |
|
| 2089 return 1; |
|
| 2090 } |
|
| 2091 |
|
| 2092 /* |
|
| 2093 * Authorization Functions |
|
| 2094 * Most of these are callbacks from dialogs. They're used by both |
|
| 2095 * methods of authorization (SSI and old-school channel 4 ICBM) |
|
| 2096 */ |
|
| 2097 /* When you ask other people for authorization */ |
|
| 2098 static void |
|
| 2099 gaim_auth_request(struct name_data *data, char *msg) |
|
| 2100 { |
|
| 2101 GaimConnection *gc; |
|
| 2102 OscarData *od; |
|
| 2103 GaimBuddy *buddy; |
|
| 2104 GaimGroup *group; |
|
| 2105 |
|
| 2106 gc = data->gc; |
|
| 2107 od = gc->proto_data; |
|
| 2108 buddy = gaim_find_buddy(gaim_connection_get_account(gc), data->name); |
|
| 2109 if (buddy != NULL) |
|
| 2110 group = gaim_buddy_get_group(buddy); |
|
| 2111 else |
|
| 2112 group = NULL; |
|
| 2113 |
|
| 2114 if (group != NULL) |
|
| 2115 { |
|
| 2116 gaim_debug_info("oscar", "ssi: adding buddy %s to group %s\n", |
|
| 2117 buddy->name, group->name); |
|
| 2118 aim_ssi_sendauthrequest(od, data->name, msg ? msg : _("Please authorize me so I can add you to my buddy list.")); |
|
| 2119 if (!aim_ssi_itemlist_finditem(od->ssi.local, group->name, buddy->name, AIM_SSI_TYPE_BUDDY)) |
|
| 2120 aim_ssi_addbuddy(od, buddy->name, group->name, gaim_buddy_get_alias_only(buddy), NULL, NULL, 1); |
|
| 2121 } |
|
| 2122 } |
|
| 2123 |
|
| 2124 static void |
|
| 2125 gaim_auth_request_msgprompt(struct name_data *data) |
|
| 2126 { |
|
| 2127 gaim_request_input(data->gc, NULL, _("Authorization Request Message:"), |
|
| 2128 NULL, _("Please authorize me!"), TRUE, FALSE, NULL, |
|
| 2129 _("OK"), G_CALLBACK(gaim_auth_request), |
|
| 2130 _("Cancel"), G_CALLBACK(oscar_free_name_data), |
|
| 2131 data); |
|
| 2132 } |
|
| 2133 |
|
| 2134 static void |
|
| 2135 gaim_auth_dontrequest(struct name_data *data) |
|
| 2136 { |
|
| 2137 GaimConnection *gc = data->gc; |
|
| 2138 GaimBuddy *b = gaim_find_buddy(gaim_connection_get_account(gc), data->name); |
|
| 2139 |
|
| 2140 /* Remove from local list */ |
|
| 2141 gaim_blist_remove_buddy(b); |
|
| 2142 |
|
| 2143 oscar_free_name_data(data); |
|
| 2144 } |
|
| 2145 |
|
| 2146 |
|
| 2147 static void |
|
| 2148 gaim_auth_sendrequest(GaimConnection *gc, char *name) |
|
| 2149 { |
|
| 2150 struct name_data *data = g_new0(struct name_data, 1); |
|
| 2151 GaimBuddy *buddy; |
|
| 2152 gchar *dialog_msg, *nombre; |
|
| 2153 |
|
| 2154 buddy = gaim_find_buddy(gc->account, name); |
|
| 2155 if (buddy && (gaim_buddy_get_alias_only(buddy))) |
|
| 2156 nombre = g_strdup_printf("%s (%s)", name, gaim_buddy_get_alias_only(buddy)); |
|
| 2157 else |
|
| 2158 nombre = NULL; |
|
| 2159 |
|
| 2160 dialog_msg = g_strdup_printf(_("The user %s requires authorization before being added to a buddy list. Do you want to send an authorization request?"), (nombre ? nombre : name)); |
|
| 2161 data->gc = gc; |
|
| 2162 data->name = g_strdup(name); |
|
| 2163 data->nick = NULL; |
|
| 2164 |
|
| 2165 gaim_request_action(gc, NULL, _("Request Authorization"), dialog_msg, |
|
| 2166 0, data, 2, |
|
| 2167 _("_Request Authorization"), |
|
| 2168 G_CALLBACK(gaim_auth_request_msgprompt), |
|
| 2169 _("Cancel"), G_CALLBACK(gaim_auth_dontrequest)); |
|
| 2170 |
|
| 2171 g_free(dialog_msg); |
|
| 2172 g_free(nombre); |
|
| 2173 } |
|
| 2174 |
|
| 2175 |
|
| 2176 static void |
|
| 2177 gaim_auth_sendrequest_menu(GaimBlistNode *node, gpointer ignored) |
|
| 2178 { |
|
| 2179 GaimBuddy *buddy; |
|
| 2180 GaimConnection *gc; |
|
| 2181 |
|
| 2182 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); |
|
| 2183 |
|
| 2184 buddy = (GaimBuddy *) node; |
|
| 2185 gc = gaim_account_get_connection(buddy->account); |
|
| 2186 gaim_auth_sendrequest(gc, buddy->name); |
|
| 2187 } |
|
| 2188 |
|
| 2189 /* When other people ask you for authorization */ |
|
| 2190 static void |
|
| 2191 gaim_auth_grant(struct name_data *data) |
|
| 2192 { |
|
| 2193 GaimConnection *gc = data->gc; |
|
| 2194 OscarData *od = gc->proto_data; |
|
| 2195 |
|
| 2196 aim_ssi_sendauthreply(od, data->name, 0x01, NULL); |
|
| 2197 |
|
| 2198 oscar_free_name_data(data); |
|
| 2199 } |
|
| 2200 |
|
| 2201 /* When other people ask you for authorization */ |
|
| 2202 static void |
|
| 2203 gaim_auth_dontgrant(struct name_data *data, char *msg) |
|
| 2204 { |
|
| 2205 GaimConnection *gc = data->gc; |
|
| 2206 OscarData *od = gc->proto_data; |
|
| 2207 |
|
| 2208 aim_ssi_sendauthreply(od, data->name, 0x00, msg ? msg : _("No reason given.")); |
|
| 2209 } |
|
| 2210 |
|
| 2211 static void |
|
| 2212 gaim_auth_dontgrant_msgprompt(struct name_data *data) |
|
| 2213 { |
|
| 2214 gaim_request_input(data->gc, NULL, _("Authorization Denied Message:"), |
|
| 2215 NULL, _("No reason given."), TRUE, FALSE, NULL, |
|
| 2216 _("OK"), G_CALLBACK(gaim_auth_dontgrant), |
|
| 2217 _("Cancel"), G_CALLBACK(oscar_free_name_data), |
|
| 2218 data); |
|
| 2219 } |
|
| 2220 |
|
| 2221 /* When someone sends you buddies */ |
|
| 2222 static void |
|
| 2223 gaim_icq_buddyadd(struct name_data *data) |
|
| 2224 { |
|
| 2225 GaimConnection *gc = data->gc; |
|
| 2226 |
|
| 2227 gaim_blist_request_add_buddy(gaim_connection_get_account(gc), data->name, NULL, data->nick); |
|
| 2228 |
|
| 2229 oscar_free_name_data(data); |
|
| 2230 } |
|
| 2231 |
|
| 2232 static int |
|
| 2233 incomingim_chan4(OscarData *od, FlapConnection *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch4_args *args, time_t t) |
|
| 2234 { |
|
| 2235 GaimConnection *gc = od->gc; |
|
| 2236 GaimAccount *account = gaim_connection_get_account(gc); |
|
| 2237 gchar **msg1, **msg2; |
|
| 2238 int i, numtoks; |
|
| 2239 |
|
| 2240 if (!args->type || !args->msg || !args->uin) |
|
| 2241 return 1; |
|
| 2242 |
|
| 2243 gaim_debug_info("oscar", |
|
| 2244 "Received a channel 4 message of type 0x%02hx.\n", |
|
| 2245 args->type); |
|
| 2246 |
|
| 2247 /* |
|
| 2248 * Split up the message at the delimeter character, then convert each |
|
| 2249 * string to UTF-8. Unless, of course, this is a type 1 message. If |
|
| 2250 * this is a type 1 message, then the delimiter 0xfe could be a valid |
|
| 2251 * character in whatever encoding the message was sent in. Type 1 |
|
| 2252 * messages are always made up of only one part, so we can easily account |
|
| 2253 * for this suck-ass part of the protocol by splitting the string into at |
|
| 2254 * most 1 baby string. |
|
| 2255 */ |
|
| 2256 msg1 = g_strsplit(args->msg, "\376", (args->type == 0x01 ? 1 : 0)); |
|
| 2257 for (numtoks=0; msg1[numtoks]; numtoks++); |
|
| 2258 msg2 = (gchar **)g_malloc((numtoks+1)*sizeof(gchar *)); |
|
| 2259 for (i=0; msg1[i]; i++) { |
|
| 2260 gaim_str_strip_char(msg1[i], '\r'); |
|
| 2261 msg2[i] = gaim_plugin_oscar_decode_im_part(account, "1", AIM_CHARSET_ASCII, 0x0000, msg1[i], strlen(msg1[i])); |
|
| 2262 } |
|
| 2263 msg2[i] = NULL; |
|
| 2264 |
|
| 2265 switch (args->type) { |
|
| 2266 case 0x01: { /* MacICQ message or basic offline message */ |
|
| 2267 if (i >= 1) { |
|
| 2268 gchar *uin = g_strdup_printf("%u", args->uin); |
|
| 2269 gchar *tmp; |
|
| 2270 |
|
| 2271 /* If the message came from an ICQ user then escape any HTML */ |
|
| 2272 tmp = g_markup_escape_text(msg2[0], -1); |
|
| 2273 |
|
| 2274 if (t) { /* This is an offline message */ |
|
| 2275 /* The timestamp is UTC-ish, so we need to get the offset */ |
|
| 2276 #ifdef HAVE_TM_GMTOFF |
|
| 2277 time_t now; |
|
| 2278 struct tm *tm; |
|
| 2279 now = time(NULL); |
|
| 2280 tm = localtime(&now); |
|
| 2281 t += tm->tm_gmtoff; |
|
| 2282 #else |
|
| 2283 # ifdef HAVE_TIMEZONE |
|
| 2284 tzset(); |
|
| 2285 t -= timezone; |
|
| 2286 # endif |
|
| 2287 #endif |
|
| 2288 serv_got_im(gc, uin, tmp, 0, t); |
|
| 2289 } else { /* This is a message from MacICQ/Miranda */ |
|
| 2290 serv_got_im(gc, uin, tmp, 0, time(NULL)); |
|
| 2291 } |
|
| 2292 g_free(uin); |
|
| 2293 g_free(tmp); |
|
| 2294 } |
|
| 2295 } break; |
|
| 2296 |
|
| 2297 case 0x04: { /* Someone sent you a URL */ |
|
| 2298 if (i >= 2) { |
|
| 2299 if (msg2[1] != NULL) { |
|
| 2300 gchar *uin = g_strdup_printf("%u", args->uin); |
|
| 2301 gchar *message = g_strdup_printf("<A HREF=\"%s\">%s</A>", |
|
| 2302 msg2[1], |
|
| 2303 (msg2[0] && msg2[0][0]) ? msg2[0] : msg2[1]); |
|
| 2304 serv_got_im(gc, uin, message, 0, time(NULL)); |
|
| 2305 g_free(uin); |
|
| 2306 g_free(message); |
|
| 2307 } |
|
| 2308 } |
|
| 2309 } break; |
|
| 2310 |
|
| 2311 case 0x06: { /* Someone requested authorization */ |
|
| 2312 if (i >= 6) { |
|
| 2313 struct name_data *data = g_new(struct name_data, 1); |
|
| 2314 gchar *sn = g_strdup_printf("%u", args->uin); |
|
| 2315 gchar *reason; |
|
| 2316 gchar *dialog_msg; |
|
| 2317 |
|
| 2318 if (msg2[5] != NULL) |
|
| 2319 reason = gaim_plugin_oscar_decode_im_part(account, sn, AIM_CHARSET_CUSTOM, 0x0000, msg2[5], strlen(msg2[5])); |
|
| 2320 else |
|
| 2321 reason = g_strdup(_("No reason given.")); |
|
| 2322 |
|
| 2323 dialog_msg = g_strdup_printf(_("The user %u wants to add %s to their buddy list for the following reason:\n%s"), |
|
| 2324 args->uin, gaim_account_get_username(gc->account), reason); |
|
| 2325 g_free(reason); |
|
| 2326 gaim_debug_info("oscar", |
|
| 2327 "Received an authorization request from UIN %u\n", |
|
| 2328 args->uin); |
|
| 2329 data->gc = gc; |
|
| 2330 data->name = sn; |
|
| 2331 data->nick = NULL; |
|
| 2332 |
|
| 2333 gaim_request_action(gc, NULL, _("Authorization Request"), |
|
| 2334 dialog_msg, GAIM_DEFAULT_ACTION_NONE, data, |
|
| 2335 2, _("_Authorize"), |
|
| 2336 G_CALLBACK(gaim_auth_grant), |
|
| 2337 _("_Deny"), |
|
| 2338 G_CALLBACK(gaim_auth_dontgrant_msgprompt)); |
|
| 2339 g_free(dialog_msg); |
|
| 2340 } |
|
| 2341 } break; |
|
| 2342 |
|
| 2343 case 0x07: { /* Someone has denied you authorization */ |
|
| 2344 if (i >= 1) { |
|
| 2345 gchar *dialog_msg = g_strdup_printf(_("The user %u has denied your request to add them to your buddy list for the following reason:\n%s"), args->uin, msg2[0] ? msg2[0] : _("No reason given.")); |
|
| 2346 gaim_notify_info(gc, NULL, _("ICQ authorization denied."), |
|
| 2347 dialog_msg); |
|
| 2348 g_free(dialog_msg); |
|
| 2349 } |
|
| 2350 } break; |
|
| 2351 |
|
| 2352 case 0x08: { /* Someone has granted you authorization */ |
|
| 2353 gchar *dialog_msg = g_strdup_printf(_("The user %u has granted your request to add them to your buddy list."), args->uin); |
|
| 2354 gaim_notify_info(gc, NULL, "ICQ authorization accepted.", |
|
| 2355 dialog_msg); |
|
| 2356 g_free(dialog_msg); |
|
| 2357 } break; |
|
| 2358 |
|
| 2359 case 0x09: { /* Message from the Godly ICQ server itself, I think */ |
|
| 2360 if (i >= 5) { |
|
| 2361 gchar *dialog_msg = g_strdup_printf(_("You have received a special message\n\nFrom: %s [%s]\n%s"), msg2[0], msg2[3], msg2[5]); |
|
| 2362 gaim_notify_info(gc, NULL, "ICQ Server Message", dialog_msg); |
|
| 2363 g_free(dialog_msg); |
|
| 2364 } |
|
| 2365 } break; |
|
| 2366 |
|
| 2367 case 0x0d: { /* Someone has sent you a pager message from http://www.icq.com/your_uin */ |
|
| 2368 if (i >= 6) { |
|
| 2369 gchar *dialog_msg = g_strdup_printf(_("You have received an ICQ page\n\nFrom: %s [%s]\n%s"), msg2[0], msg2[3], msg2[5]); |
|
| 2370 gaim_notify_info(gc, NULL, "ICQ Page", dialog_msg); |
|
| 2371 g_free(dialog_msg); |
|
| 2372 } |
|
| 2373 } break; |
|
| 2374 |
|
| 2375 case 0x0e: { /* Someone has emailed you at your_uin@pager.icq.com */ |
|
| 2376 if (i >= 6) { |
|
| 2377 gchar *dialog_msg = g_strdup_printf(_("You have received an ICQ e-mail from %s [%s]\n\nMessage is:\n%s"), msg2[0], msg2[3], msg2[5]); |
|
| 2378 gaim_notify_info(gc, NULL, "ICQ E-Mail", dialog_msg); |
|
| 2379 g_free(dialog_msg); |
|
| 2380 } |
|
| 2381 } break; |
|
| 2382 |
|
| 2383 case 0x12: { |
|
| 2384 /* Ack for authorizing/denying someone. Or possibly an ack for sending any system notice */ |
|
| 2385 /* Someone added you to their buddy list? */ |
|
| 2386 } break; |
|
| 2387 |
|
| 2388 case 0x13: { /* Someone has sent you some ICQ buddies */ |
|
| 2389 guint i, num; |
|
| 2390 gchar **text; |
|
| 2391 text = g_strsplit(args->msg, "\376", 0); |
|
| 2392 if (text) { |
|
| 2393 num = 0; |
|
| 2394 for (i=0; i<strlen(text[0]); i++) |
|
| 2395 num = num*10 + text[0][i]-48; |
|
| 2396 for (i=0; i<num; i++) { |
|
| 2397 struct name_data *data = g_new(struct name_data, 1); |
|
| 2398 gchar *message = g_strdup_printf(_("ICQ user %u has sent you a buddy: %s (%s)"), args->uin, text[i*2+2], text[i*2+1]); |
|
| 2399 data->gc = gc; |
|
| 2400 data->name = g_strdup(text[i*2+1]); |
|
| 2401 data->nick = g_strdup(text[i*2+2]); |
|
| 2402 |
|
| 2403 gaim_request_action(gc, NULL, message, |
|
| 2404 _("Do you want to add this buddy " |
|
| 2405 "to your buddy list?"), |
|
| 2406 GAIM_DEFAULT_ACTION_NONE, data, 2, |
|
| 2407 _("Add"), G_CALLBACK(gaim_icq_buddyadd), |
|
| 2408 _("_Decline"), G_CALLBACK(oscar_free_name_data)); |
|
| 2409 g_free(message); |
|
| 2410 } |
|
| 2411 g_strfreev(text); |
|
| 2412 } |
|
| 2413 } break; |
|
| 2414 |
|
| 2415 case 0x1a: { /* Someone has sent you a greeting card or requested buddies? */ |
|
| 2416 /* This is boring and silly. */ |
|
| 2417 } break; |
|
| 2418 |
|
| 2419 default: { |
|
| 2420 gaim_debug_info("oscar", |
|
| 2421 "Received a channel 4 message of unknown type " |
|
| 2422 "(type 0x%02hhx).\n", args->type); |
|
| 2423 } break; |
|
| 2424 } |
|
| 2425 |
|
| 2426 g_strfreev(msg1); |
|
| 2427 g_strfreev(msg2); |
|
| 2428 |
|
| 2429 return 1; |
|
| 2430 } |
|
| 2431 |
|
| 2432 static int gaim_parse_incoming_im(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 2433 guint16 channel; |
|
| 2434 int ret = 0; |
|
| 2435 aim_userinfo_t *userinfo; |
|
| 2436 va_list ap; |
|
| 2437 |
|
| 2438 va_start(ap, fr); |
|
| 2439 channel = (guint16)va_arg(ap, unsigned int); |
|
| 2440 userinfo = va_arg(ap, aim_userinfo_t *); |
|
| 2441 |
|
| 2442 switch (channel) { |
|
| 2443 case 1: { /* standard message */ |
|
| 2444 struct aim_incomingim_ch1_args *args; |
|
| 2445 args = va_arg(ap, struct aim_incomingim_ch1_args *); |
|
| 2446 ret = incomingim_chan1(od, conn, userinfo, args); |
|
| 2447 } break; |
|
| 2448 |
|
| 2449 case 2: { /* rendezvous */ |
|
| 2450 IcbmArgsCh2 *args; |
|
| 2451 args = va_arg(ap, IcbmArgsCh2 *); |
|
| 2452 ret = incomingim_chan2(od, conn, userinfo, args); |
|
| 2453 } break; |
|
| 2454 |
|
| 2455 case 4: { /* ICQ */ |
|
| 2456 struct aim_incomingim_ch4_args *args; |
|
| 2457 args = va_arg(ap, struct aim_incomingim_ch4_args *); |
|
| 2458 ret = incomingim_chan4(od, conn, userinfo, args, 0); |
|
| 2459 } break; |
|
| 2460 |
|
| 2461 default: { |
|
| 2462 gaim_debug_warning("oscar", |
|
| 2463 "ICBM received on unsupported channel (channel " |
|
| 2464 "0x%04hx).", channel); |
|
| 2465 } break; |
|
| 2466 } |
|
| 2467 |
|
| 2468 va_end(ap); |
|
| 2469 |
|
| 2470 return ret; |
|
| 2471 } |
|
| 2472 |
|
| 2473 static int gaim_parse_misses(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 2474 GaimConnection *gc = od->gc; |
|
| 2475 GaimAccount *account = gaim_connection_get_account(gc); |
|
| 2476 char *buf; |
|
| 2477 va_list ap; |
|
| 2478 guint16 chan, nummissed, reason; |
|
| 2479 aim_userinfo_t *userinfo; |
|
| 2480 |
|
| 2481 va_start(ap, fr); |
|
| 2482 chan = (guint16)va_arg(ap, unsigned int); |
|
| 2483 userinfo = va_arg(ap, aim_userinfo_t *); |
|
| 2484 nummissed = (guint16)va_arg(ap, unsigned int); |
|
| 2485 reason = (guint16)va_arg(ap, unsigned int); |
|
| 2486 va_end(ap); |
|
| 2487 |
|
| 2488 switch(reason) { |
|
| 2489 case 0: /* Invalid (0) */ |
|
| 2490 buf = g_strdup_printf( |
|
| 2491 ngettext( |
|
| 2492 "You missed %hu message from %s because it was invalid.", |
|
| 2493 "You missed %hu messages from %s because they were invalid.", |
|
| 2494 nummissed), |
|
| 2495 nummissed, |
|
| 2496 userinfo->sn); |
|
| 2497 break; |
|
| 2498 case 1: /* Message too large */ |
|
| 2499 buf = g_strdup_printf( |
|
| 2500 ngettext( |
|
| 2501 "You missed %hu message from %s because it was too large.", |
|
| 2502 "You missed %hu messages from %s because they were too large.", |
|
| 2503 nummissed), |
|
| 2504 nummissed, |
|
| 2505 userinfo->sn); |
|
| 2506 break; |
|
| 2507 case 2: /* Rate exceeded */ |
|
| 2508 buf = g_strdup_printf( |
|
| 2509 ngettext( |
|
| 2510 "You missed %hu message from %s because the rate limit has been exceeded.", |
|
| 2511 "You missed %hu messages from %s because the rate limit has been exceeded.", |
|
| 2512 nummissed), |
|
| 2513 nummissed, |
|
| 2514 userinfo->sn); |
|
| 2515 break; |
|
| 2516 case 3: /* Evil Sender */ |
|
| 2517 buf = g_strdup_printf( |
|
| 2518 ngettext( |
|
| 2519 "You missed %hu message from %s because he/she was too evil.", |
|
| 2520 "You missed %hu messages from %s because he/she was too evil.", |
|
| 2521 nummissed), |
|
| 2522 nummissed, |
|
| 2523 userinfo->sn); |
|
| 2524 break; |
|
| 2525 case 4: /* Evil Receiver */ |
|
| 2526 buf = g_strdup_printf( |
|
| 2527 ngettext( |
|
| 2528 "You missed %hu message from %s because you are too evil.", |
|
| 2529 "You missed %hu messages from %s because you are too evil.", |
|
| 2530 nummissed), |
|
| 2531 nummissed, |
|
| 2532 userinfo->sn); |
|
| 2533 break; |
|
| 2534 default: |
|
| 2535 buf = g_strdup_printf( |
|
| 2536 ngettext( |
|
| 2537 "You missed %hu message from %s for an unknown reason.", |
|
| 2538 "You missed %hu messages from %s for an unknown reason.", |
|
| 2539 nummissed), |
|
| 2540 nummissed, |
|
| 2541 userinfo->sn); |
|
| 2542 break; |
|
| 2543 } |
|
| 2544 |
|
| 2545 if (!gaim_conv_present_error(userinfo->sn, account, buf)) |
|
| 2546 gaim_notify_error(od->gc, NULL, buf, NULL); |
|
| 2547 g_free(buf); |
|
| 2548 |
|
| 2549 return 1; |
|
| 2550 } |
|
| 2551 |
|
| 2552 static int |
|
| 2553 gaim_parse_clientauto_ch2(OscarData *od, const char *who, guint16 reason, const guchar *cookie) |
|
| 2554 { |
|
| 2555 if (reason == 0x0003) |
|
| 2556 { |
|
| 2557 /* Rendezvous was refused. */ |
|
| 2558 PeerConnection *conn; |
|
| 2559 |
|
| 2560 conn = peer_connection_find_by_cookie(od, who, cookie); |
|
| 2561 |
|
| 2562 if (conn == NULL) |
|
| 2563 { |
|
| 2564 gaim_debug_info("oscar", "Received a rendezvous cancel message " |
|
| 2565 "for a nonexistant connection from %s.\n", who); |
|
| 2566 } |
|
| 2567 else |
|
| 2568 { |
|
| 2569 peer_connection_destroy(conn, OSCAR_DISCONNECT_REMOTE_REFUSED); |
|
| 2570 } |
|
| 2571 } |
|
| 2572 else |
|
| 2573 { |
|
| 2574 gaim_debug_warning("oscar", "Received an unknown rendezvous " |
|
| 2575 "message from %s. Type 0x%04hx\n", who, reason); |
|
| 2576 } |
|
| 2577 |
|
| 2578 return 0; |
|
| 2579 } |
|
| 2580 |
|
| 2581 static int gaim_parse_clientauto_ch4(OscarData *od, char *who, guint16 reason, guint32 state, char *msg) { |
|
| 2582 GaimConnection *gc = od->gc; |
|
| 2583 |
|
| 2584 switch(reason) { |
|
| 2585 case 0x0003: { /* Reply from an ICQ status message request */ |
|
| 2586 char *title, *statusmsg, **splitmsg, *dialogmsg; |
|
| 2587 |
|
| 2588 title = g_strdup_printf(_("Info for %s"), who); |
|
| 2589 |
|
| 2590 /* Split at (carriage return/newline)'s, then rejoin later with BRs between. */ |
|
| 2591 statusmsg = oscar_icqstatus(state); |
|
| 2592 splitmsg = g_strsplit(msg, "\r\n", 0); |
|
| 2593 dialogmsg = g_strdup_printf(_("<B>UIN:</B> %s<BR><B>Status:</B> %s<HR>%s"), who, statusmsg, g_strjoinv("<BR>", splitmsg)); |
|
| 2594 g_free(statusmsg); |
|
| 2595 g_strfreev(splitmsg); |
|
| 2596 |
|
| 2597 gaim_notify_userinfo(gc, who, dialogmsg, NULL, NULL); |
|
| 2598 |
|
| 2599 g_free(title); |
|
| 2600 g_free(dialogmsg); |
|
| 2601 } break; |
|
| 2602 |
|
| 2603 default: { |
|
| 2604 gaim_debug_warning("oscar", |
|
| 2605 "Received an unknown client auto-response from %s. " |
|
| 2606 "Type 0x%04hx\n", who, reason); |
|
| 2607 } break; |
|
| 2608 } /* end of switch */ |
|
| 2609 |
|
| 2610 return 0; |
|
| 2611 } |
|
| 2612 |
|
| 2613 static int gaim_parse_clientauto(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 2614 va_list ap; |
|
| 2615 guint16 chan, reason; |
|
| 2616 char *who; |
|
| 2617 |
|
| 2618 va_start(ap, fr); |
|
| 2619 chan = (guint16)va_arg(ap, unsigned int); |
|
| 2620 who = va_arg(ap, char *); |
|
| 2621 reason = (guint16)va_arg(ap, unsigned int); |
|
| 2622 |
|
| 2623 if (chan == 0x0002) { /* File transfer declined */ |
|
| 2624 guchar *cookie = va_arg(ap, guchar *); |
|
| 2625 return gaim_parse_clientauto_ch2(od, who, reason, cookie); |
|
| 2626 } else if (chan == 0x0004) { /* ICQ message */ |
|
| 2627 guint32 state = 0; |
|
| 2628 char *msg = NULL; |
|
| 2629 if (reason == 0x0003) { |
|
| 2630 state = va_arg(ap, guint32); |
|
| 2631 msg = va_arg(ap, char *); |
|
| 2632 } |
|
| 2633 return gaim_parse_clientauto_ch4(od, who, reason, state, msg); |
|
| 2634 } |
|
| 2635 |
|
| 2636 va_end(ap); |
|
| 2637 |
|
| 2638 return 1; |
|
| 2639 } |
|
| 2640 |
|
| 2641 static int gaim_parse_genericerr(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 2642 va_list ap; |
|
| 2643 guint16 reason; |
|
| 2644 char *m; |
|
| 2645 |
|
| 2646 va_start(ap, fr); |
|
| 2647 reason = (guint16) va_arg(ap, unsigned int); |
|
| 2648 va_end(ap); |
|
| 2649 |
|
| 2650 gaim_debug_error("oscar", |
|
| 2651 "snac threw error (reason 0x%04hx: %s)\n", reason, |
|
| 2652 (reason < msgerrreasonlen) ? msgerrreason[reason] : "unknown"); |
|
| 2653 |
|
| 2654 m = g_strdup_printf(_("SNAC threw error: %s\n"), |
|
| 2655 reason < msgerrreasonlen ? _(msgerrreason[reason]) : _("Unknown error")); |
|
| 2656 gaim_notify_error(od->gc, NULL, m, NULL); |
|
| 2657 g_free(m); |
|
| 2658 |
|
| 2659 return 1; |
|
| 2660 } |
|
| 2661 |
|
| 2662 static int gaim_parse_msgerr(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 2663 GaimConnection *gc = od->gc; |
|
| 2664 #ifdef TODOFT |
|
| 2665 OscarData *od = gc->proto_data; |
|
| 2666 GaimXfer *xfer; |
|
| 2667 #endif |
|
| 2668 va_list ap; |
|
| 2669 guint16 reason; |
|
| 2670 char *data, *buf; |
|
| 2671 |
|
| 2672 va_start(ap, fr); |
|
| 2673 reason = (guint16)va_arg(ap, unsigned int); |
|
| 2674 data = va_arg(ap, char *); |
|
| 2675 va_end(ap); |
|
| 2676 |
|
| 2677 gaim_debug_error("oscar", |
|
| 2678 "Message error with data %s and reason %hu\n", |
|
| 2679 (data != NULL ? data : ""), reason); |
|
| 2680 |
|
| 2681 #ifdef TODOFT |
|
| 2682 /* If this was a file transfer request, data is a cookie */ |
|
| 2683 if ((xfer = oscar_find_xfer_by_cookie(od->file_transfers, data))) { |
|
| 2684 gaim_xfer_cancel_remote(xfer); |
|
| 2685 return 1; |
|
| 2686 } |
|
| 2687 #endif |
|
| 2688 |
|
| 2689 /* Data is assumed to be the destination sn */ |
|
| 2690 buf = g_strdup_printf(_("Unable to send message: %s"), (reason < msgerrreasonlen) ? msgerrreason[reason] : _("Unknown reason.")); |
|
| 2691 if (!gaim_conv_present_error(data, gaim_connection_get_account(gc), buf)) { |
|
| 2692 g_free(buf); |
|
| 2693 buf = g_strdup_printf(_("Unable to send message to %s:"), data ? data : "(unknown)"); |
|
| 2694 gaim_notify_error(od->gc, NULL, buf, |
|
| 2695 (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("Unknown reason.")); |
|
| 2696 } |
|
| 2697 g_free(buf); |
|
| 2698 |
|
| 2699 return 1; |
|
| 2700 } |
|
| 2701 |
|
| 2702 static int gaim_parse_mtn(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 2703 GaimConnection *gc = od->gc; |
|
| 2704 va_list ap; |
|
| 2705 guint16 type1, type2; |
|
| 2706 char *sn; |
|
| 2707 |
|
| 2708 va_start(ap, fr); |
|
| 2709 type1 = (guint16) va_arg(ap, unsigned int); |
|
| 2710 sn = va_arg(ap, char *); |
|
| 2711 type2 = (guint16) va_arg(ap, unsigned int); |
|
| 2712 va_end(ap); |
|
| 2713 |
|
| 2714 switch (type2) { |
|
| 2715 case 0x0000: { /* Text has been cleared */ |
|
| 2716 serv_got_typing_stopped(gc, sn); |
|
| 2717 } break; |
|
| 2718 |
|
| 2719 case 0x0001: { /* Paused typing */ |
|
| 2720 serv_got_typing(gc, sn, 0, GAIM_TYPED); |
|
| 2721 } break; |
|
| 2722 |
|
| 2723 case 0x0002: { /* Typing */ |
|
| 2724 serv_got_typing(gc, sn, 0, GAIM_TYPING); |
|
| 2725 } break; |
|
| 2726 |
|
| 2727 default: { |
|
| 2728 /* |
|
| 2729 * It looks like iChat sometimes sends typing notification |
|
| 2730 * with type1=0x0001 and type2=0x000f. Not sure why. |
|
| 2731 */ |
|
| 2732 gaim_debug_info("oscar", "Received unknown typing notification message from %s. Type1 is 0x%04x and type2 is 0x%04hx.\n", sn, type1, type2); |
|
| 2733 } break; |
|
| 2734 } |
|
| 2735 |
|
| 2736 return 1; |
|
| 2737 } |
|
| 2738 |
|
| 2739 /* |
|
| 2740 * We get this error when there was an error in the locate family. This |
|
| 2741 * happens when you request info of someone who is offline. |
|
| 2742 */ |
|
| 2743 static int gaim_parse_locerr(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 2744 gchar *buf; |
|
| 2745 va_list ap; |
|
| 2746 guint16 reason; |
|
| 2747 char *destn; |
|
| 2748 |
|
| 2749 va_start(ap, fr); |
|
| 2750 reason = (guint16) va_arg(ap, unsigned int); |
|
| 2751 destn = va_arg(ap, char *); |
|
| 2752 va_end(ap); |
|
| 2753 |
|
| 2754 if (destn == NULL) |
|
| 2755 return 1; |
|
| 2756 |
|
| 2757 buf = g_strdup_printf(_("User information not available: %s"), (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("Unknown reason.")); |
|
| 2758 if (!gaim_conv_present_error(destn, gaim_connection_get_account((GaimConnection*)od->gc), buf)) { |
|
| 2759 g_free(buf); |
|
| 2760 buf = g_strdup_printf(_("User information for %s unavailable:"), destn); |
|
| 2761 gaim_notify_error(od->gc, NULL, buf, (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("Unknown reason.")); |
|
| 2762 } |
|
| 2763 g_free(buf); |
|
| 2764 |
|
| 2765 return 1; |
|
| 2766 } |
|
| 2767 |
|
| 2768 static int gaim_parse_userinfo(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 2769 GaimConnection *gc = od->gc; |
|
| 2770 GaimAccount *account = gaim_connection_get_account(gc); |
|
| 2771 GString *str; |
|
| 2772 gchar *tmp = NULL, *info_utf8 = NULL, *away_utf8 = NULL; |
|
| 2773 va_list ap; |
|
| 2774 aim_userinfo_t *userinfo; |
|
| 2775 |
|
| 2776 va_start(ap, fr); |
|
| 2777 userinfo = va_arg(ap, aim_userinfo_t *); |
|
| 2778 va_end(ap); |
|
| 2779 |
|
| 2780 str = g_string_new(""); |
|
| 2781 g_string_append_printf(str, "<b>%s:</b> %s", _("Screen Name"), userinfo->sn); |
|
| 2782 g_string_append_printf(str, "\n<br><b>%s</b>: %d%%", _("Warning Level"), (int)((userinfo->warnlevel/10.0) + 0.5)); |
|
| 2783 |
|
| 2784 if (userinfo->present & AIM_USERINFO_PRESENT_ONLINESINCE) { |
|
| 2785 time_t t = userinfo->onlinesince - od->timeoffset; |
|
| 2786 oscar_string_append(str, "\n<br>", _("Online Since"), gaim_date_format_full(localtime(&t))); |
|
| 2787 } |
|
| 2788 |
|
| 2789 if (userinfo->present & AIM_USERINFO_PRESENT_MEMBERSINCE) { |
|
| 2790 time_t t = userinfo->membersince - od->timeoffset; |
|
| 2791 oscar_string_append(str, "\n<br>", _("Member Since"), gaim_date_format_full(localtime(&t))); |
|
| 2792 } |
|
| 2793 |
|
| 2794 if (userinfo->capabilities != 0) { |
|
| 2795 tmp = oscar_caps_to_string(userinfo->capabilities); |
|
| 2796 oscar_string_append(str, "\n<br>", _("Capabilities"), tmp); |
|
| 2797 g_free(tmp); |
|
| 2798 } |
|
| 2799 |
|
| 2800 if (userinfo->present & AIM_USERINFO_PRESENT_IDLE) { |
|
| 2801 tmp = gaim_str_seconds_to_string(userinfo->idletime*60); |
|
| 2802 oscar_string_append(str, "\n<br>", _("Idle"), tmp); |
|
| 2803 g_free(tmp); |
|
| 2804 } |
|
| 2805 |
|
| 2806 oscar_string_append_info(gc, str, "\n<br>", NULL, userinfo); |
|
| 2807 |
|
| 2808 /* Available message */ |
|
| 2809 if ((userinfo->status != NULL) && !(userinfo->flags & AIM_FLAG_AWAY)) |
|
| 2810 { |
|
| 2811 if (userinfo->status[0] != '\0') |
|
| 2812 tmp = oscar_encoding_to_utf8(userinfo->status_encoding, |
|
| 2813 userinfo->status, userinfo->status_len); |
|
| 2814 oscar_string_convert_and_append(account, str, "\n<br>", _("Available Message"), tmp); |
|
| 2815 g_free(tmp); |
|
| 2816 } |
|
| 2817 |
|
| 2818 /* Away message */ |
|
| 2819 if ((userinfo->flags & AIM_FLAG_AWAY) && (userinfo->away_len > 0) && (userinfo->away != NULL) && (userinfo->away_encoding != NULL)) { |
|
| 2820 tmp = oscar_encoding_extract(userinfo->away_encoding); |
|
| 2821 away_utf8 = oscar_encoding_to_utf8(tmp, userinfo->away, userinfo->away_len); |
|
| 2822 g_free(tmp); |
|
| 2823 if (away_utf8 != NULL) { |
|
| 2824 g_string_append_printf(str, "\n<hr>%s", away_utf8); |
|
| 2825 g_free(away_utf8); |
|
| 2826 } |
|
| 2827 } |
|
| 2828 |
|
| 2829 /* Info */ |
|
| 2830 if ((userinfo->info_len > 0) && (userinfo->info != NULL) && (userinfo->info_encoding != NULL)) { |
|
| 2831 tmp = oscar_encoding_extract(userinfo->info_encoding); |
|
| 2832 info_utf8 = oscar_encoding_to_utf8(tmp, userinfo->info, userinfo->info_len); |
|
| 2833 g_free(tmp); |
|
| 2834 if (info_utf8 != NULL) { |
|
| 2835 g_string_append_printf(str, "\n<hr>%s", info_utf8); |
|
| 2836 g_free(info_utf8); |
|
| 2837 } |
|
| 2838 } |
|
| 2839 |
|
| 2840 tmp = gaim_str_sub_away_formatters(str->str, gaim_account_get_username(account)); |
|
| 2841 g_string_free(str, TRUE); |
|
| 2842 gaim_str_strip_char(tmp, '\r'); |
|
| 2843 gaim_notify_userinfo(gc, userinfo->sn, tmp, NULL, NULL); |
|
| 2844 g_free(tmp); |
|
| 2845 |
|
| 2846 return 1; |
|
| 2847 } |
|
| 2848 |
|
| 2849 static int gaim_got_infoblock(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) |
|
| 2850 { |
|
| 2851 GaimConnection *gc = od->gc; |
|
| 2852 GaimBuddy *b; |
|
| 2853 GaimPresence *presence; |
|
| 2854 GaimStatus *status; |
|
| 2855 gchar *message = NULL; |
|
| 2856 |
|
| 2857 va_list ap; |
|
| 2858 aim_userinfo_t *userinfo; |
|
| 2859 |
|
| 2860 va_start(ap, fr); |
|
| 2861 userinfo = va_arg(ap, aim_userinfo_t *); |
|
| 2862 va_end(ap); |
|
| 2863 |
|
| 2864 b = gaim_find_buddy(gaim_connection_get_account(gc), userinfo->sn); |
|
| 2865 if (b == NULL) |
|
| 2866 return 1; |
|
| 2867 |
|
| 2868 if (!aim_sn_is_icq(userinfo->sn)) |
|
| 2869 { |
|
| 2870 if (strcmp(gaim_buddy_get_name(b), userinfo->sn)) |
|
| 2871 serv_got_alias(gc, gaim_buddy_get_name(b), userinfo->sn); |
|
| 2872 else |
|
| 2873 serv_got_alias(gc, gaim_buddy_get_name(b), NULL); |
|
| 2874 } |
|
| 2875 |
|
| 2876 presence = gaim_buddy_get_presence(b); |
|
| 2877 status = gaim_presence_get_active_status(presence); |
|
| 2878 |
|
| 2879 if (!gaim_status_is_available(status) && gaim_status_is_online(status)) |
|
| 2880 { |
|
| 2881 if ((userinfo->flags & AIM_FLAG_AWAY) && |
|
| 2882 (userinfo->away_len > 0) && (userinfo->away != NULL) && (userinfo->away_encoding != NULL)) { |
|
| 2883 gchar *charset = oscar_encoding_extract(userinfo->away_encoding); |
|
| 2884 message = oscar_encoding_to_utf8(charset, userinfo->away, userinfo->away_len); |
|
| 2885 g_free(charset); |
|
| 2886 gaim_status_set_attr_string(status, "message", message); |
|
| 2887 g_free(message); |
|
| 2888 } |
|
| 2889 else |
|
| 2890 /* Set an empty message so that we know not to show "pending" */ |
|
| 2891 gaim_status_set_attr_string(status, "message", ""); |
|
| 2892 |
|
| 2893 gaim_blist_update_buddy_status(b, status); |
|
| 2894 } |
|
| 2895 |
|
| 2896 return 1; |
|
| 2897 } |
|
| 2898 |
|
| 2899 static int gaim_parse_motd(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) |
|
| 2900 { |
|
| 2901 char *msg; |
|
| 2902 guint16 id; |
|
| 2903 va_list ap; |
|
| 2904 |
|
| 2905 va_start(ap, fr); |
|
| 2906 id = (guint16) va_arg(ap, unsigned int); |
|
| 2907 msg = va_arg(ap, char *); |
|
| 2908 va_end(ap); |
|
| 2909 |
|
| 2910 gaim_debug_misc("oscar", |
|
| 2911 "MOTD: %s (%hu)\n", msg ? msg : "Unknown", id); |
|
| 2912 if (id < 4) |
|
| 2913 gaim_notify_warning(od->gc, NULL, |
|
| 2914 _("Your AIM connection may be lost."), NULL); |
|
| 2915 |
|
| 2916 return 1; |
|
| 2917 } |
|
| 2918 |
|
| 2919 static int gaim_chatnav_info(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 2920 va_list ap; |
|
| 2921 guint16 type; |
|
| 2922 |
|
| 2923 va_start(ap, fr); |
|
| 2924 type = (guint16) va_arg(ap, unsigned int); |
|
| 2925 |
|
| 2926 switch(type) { |
|
| 2927 case 0x0002: { |
|
| 2928 guint8 maxrooms; |
|
| 2929 struct aim_chat_exchangeinfo *exchanges; |
|
| 2930 int exchangecount, i; |
|
| 2931 |
|
| 2932 maxrooms = (guint8) va_arg(ap, unsigned int); |
|
| 2933 exchangecount = va_arg(ap, int); |
|
| 2934 exchanges = va_arg(ap, struct aim_chat_exchangeinfo *); |
|
| 2935 |
|
| 2936 gaim_debug_misc("oscar", "chat info: Chat Rights:\n"); |
|
| 2937 gaim_debug_misc("oscar", |
|
| 2938 "chat info: \tMax Concurrent Rooms: %hhd\n", maxrooms); |
|
| 2939 gaim_debug_misc("oscar", |
|
| 2940 "chat info: \tExchange List: (%d total)\n", exchangecount); |
|
| 2941 for (i = 0; i < exchangecount; i++) |
|
| 2942 gaim_debug_misc("oscar", |
|
| 2943 "chat info: \t\t%hu %s\n", |
|
| 2944 exchanges[i].number, exchanges[i].name ? exchanges[i].name : ""); |
|
| 2945 while (od->create_rooms) { |
|
| 2946 struct create_room *cr = od->create_rooms->data; |
|
| 2947 gaim_debug_info("oscar", |
|
| 2948 "creating room %s\n", cr->name); |
|
| 2949 aim_chatnav_createroom(od, conn, cr->name, cr->exchange); |
|
| 2950 g_free(cr->name); |
|
| 2951 od->create_rooms = g_slist_remove(od->create_rooms, cr); |
|
| 2952 g_free(cr); |
|
| 2953 } |
|
| 2954 } |
|
| 2955 break; |
|
| 2956 case 0x0008: { |
|
| 2957 char *fqcn, *name, *ck; |
|
| 2958 guint16 instance, flags, maxmsglen, maxoccupancy, unknown, exchange; |
|
| 2959 guint8 createperms; |
|
| 2960 guint32 createtime; |
|
| 2961 |
|
| 2962 fqcn = va_arg(ap, char *); |
|
| 2963 instance = (guint16)va_arg(ap, unsigned int); |
|
| 2964 exchange = (guint16)va_arg(ap, unsigned int); |
|
| 2965 flags = (guint16)va_arg(ap, unsigned int); |
|
| 2966 createtime = va_arg(ap, guint32); |
|
| 2967 maxmsglen = (guint16)va_arg(ap, unsigned int); |
|
| 2968 maxoccupancy = (guint16)va_arg(ap, unsigned int); |
|
| 2969 createperms = (guint8)va_arg(ap, unsigned int); |
|
| 2970 unknown = (guint16)va_arg(ap, unsigned int); |
|
| 2971 name = va_arg(ap, char *); |
|
| 2972 ck = va_arg(ap, char *); |
|
| 2973 |
|
| 2974 gaim_debug_misc("oscar", |
|
| 2975 "created room: %s %hu %hu %hu %u %hu %hu %hhu %hu %s %s\n", |
|
| 2976 fqcn, exchange, instance, flags, createtime, |
|
| 2977 maxmsglen, maxoccupancy, createperms, unknown, |
|
| 2978 name, ck); |
|
| 2979 aim_chat_join(od, exchange, ck, instance); |
|
| 2980 } |
|
| 2981 break; |
|
| 2982 default: |
|
| 2983 gaim_debug_warning("oscar", |
|
| 2984 "chatnav info: unknown type (%04hx)\n", type); |
|
| 2985 break; |
|
| 2986 } |
|
| 2987 |
|
| 2988 va_end(ap); |
|
| 2989 |
|
| 2990 return 1; |
|
| 2991 } |
|
| 2992 |
|
| 2993 static int gaim_conv_chat_join(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 2994 va_list ap; |
|
| 2995 int count, i; |
|
| 2996 aim_userinfo_t *info; |
|
| 2997 GaimConnection *gc = od->gc; |
|
| 2998 |
|
| 2999 struct chat_connection *c = NULL; |
|
| 3000 |
|
| 3001 va_start(ap, fr); |
|
| 3002 count = va_arg(ap, int); |
|
| 3003 info = va_arg(ap, aim_userinfo_t *); |
|
| 3004 va_end(ap); |
|
| 3005 |
|
| 3006 c = find_oscar_chat_by_conn(gc, conn); |
|
| 3007 if (!c) |
|
| 3008 return 1; |
|
| 3009 |
|
| 3010 for (i = 0; i < count; i++) |
|
| 3011 gaim_conv_chat_add_user(GAIM_CONV_CHAT(c->conv), info[i].sn, NULL, GAIM_CBFLAGS_NONE, TRUE); |
|
| 3012 |
|
| 3013 return 1; |
|
| 3014 } |
|
| 3015 |
|
| 3016 static int gaim_conv_chat_leave(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 3017 va_list ap; |
|
| 3018 int count, i; |
|
| 3019 aim_userinfo_t *info; |
|
| 3020 GaimConnection *gc = od->gc; |
|
| 3021 |
|
| 3022 struct chat_connection *c = NULL; |
|
| 3023 |
|
| 3024 va_start(ap, fr); |
|
| 3025 count = va_arg(ap, int); |
|
| 3026 info = va_arg(ap, aim_userinfo_t *); |
|
| 3027 va_end(ap); |
|
| 3028 |
|
| 3029 c = find_oscar_chat_by_conn(gc, conn); |
|
| 3030 if (!c) |
|
| 3031 return 1; |
|
| 3032 |
|
| 3033 for (i = 0; i < count; i++) |
|
| 3034 gaim_conv_chat_remove_user(GAIM_CONV_CHAT(c->conv), info[i].sn, NULL); |
|
| 3035 |
|
| 3036 return 1; |
|
| 3037 } |
|
| 3038 |
|
| 3039 static int gaim_conv_chat_info_update(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 3040 va_list ap; |
|
| 3041 aim_userinfo_t *userinfo; |
|
| 3042 struct aim_chat_roominfo *roominfo; |
|
| 3043 char *roomname; |
|
| 3044 int usercount; |
|
| 3045 char *roomdesc; |
|
| 3046 guint16 unknown_c9, unknown_d2, unknown_d5, maxmsglen, maxvisiblemsglen; |
|
| 3047 guint32 creationtime; |
|
| 3048 GaimConnection *gc = od->gc; |
|
| 3049 struct chat_connection *ccon = find_oscar_chat_by_conn(gc, conn); |
|
| 3050 |
|
| 3051 va_start(ap, fr); |
|
| 3052 roominfo = va_arg(ap, struct aim_chat_roominfo *); |
|
| 3053 roomname = va_arg(ap, char *); |
|
| 3054 usercount= va_arg(ap, int); |
|
| 3055 userinfo = va_arg(ap, aim_userinfo_t *); |
|
| 3056 roomdesc = va_arg(ap, char *); |
|
| 3057 unknown_c9 = (guint16)va_arg(ap, unsigned int); |
|
| 3058 creationtime = va_arg(ap, guint32); |
|
| 3059 maxmsglen = (guint16)va_arg(ap, unsigned int); |
|
| 3060 unknown_d2 = (guint16)va_arg(ap, unsigned int); |
|
| 3061 unknown_d5 = (guint16)va_arg(ap, unsigned int); |
|
| 3062 maxvisiblemsglen = (guint16)va_arg(ap, unsigned int); |
|
| 3063 va_end(ap); |
|
| 3064 |
|
| 3065 gaim_debug_misc("oscar", |
|
| 3066 "inside chat_info_update (maxmsglen = %hu, maxvislen = %hu)\n", |
|
| 3067 maxmsglen, maxvisiblemsglen); |
|
| 3068 |
|
| 3069 ccon->maxlen = maxmsglen; |
|
| 3070 ccon->maxvis = maxvisiblemsglen; |
|
| 3071 |
|
| 3072 return 1; |
|
| 3073 } |
|
| 3074 |
|
| 3075 static int gaim_conv_chat_incoming_msg(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 3076 GaimConnection *gc = od->gc; |
|
| 3077 struct chat_connection *ccon = find_oscar_chat_by_conn(gc, conn); |
|
| 3078 gchar *utf8; |
|
| 3079 va_list ap; |
|
| 3080 aim_userinfo_t *info; |
|
| 3081 int len; |
|
| 3082 char *msg; |
|
| 3083 char *charset; |
|
| 3084 |
|
| 3085 va_start(ap, fr); |
|
| 3086 info = va_arg(ap, aim_userinfo_t *); |
|
| 3087 len = va_arg(ap, int); |
|
| 3088 msg = va_arg(ap, char *); |
|
| 3089 charset = va_arg(ap, char *); |
|
| 3090 va_end(ap); |
|
| 3091 |
|
| 3092 utf8 = oscar_encoding_to_utf8(charset, msg, len); |
|
| 3093 if (utf8 == NULL) |
|
| 3094 /* The conversion failed! */ |
|
| 3095 utf8 = g_strdup(_("[Unable to display a message from this user because it contained invalid characters.]")); |
|
| 3096 serv_got_chat_in(gc, ccon->id, info->sn, 0, utf8, time((time_t)NULL)); |
|
| 3097 g_free(utf8); |
|
| 3098 |
|
| 3099 return 1; |
|
| 3100 } |
|
| 3101 |
|
| 3102 static int gaim_email_parseupdate(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 3103 va_list ap; |
|
| 3104 GaimConnection *gc = od->gc; |
|
| 3105 struct aim_emailinfo *emailinfo; |
|
| 3106 int havenewmail; |
|
| 3107 char *alertitle, *alerturl; |
|
| 3108 |
|
| 3109 va_start(ap, fr); |
|
| 3110 emailinfo = va_arg(ap, struct aim_emailinfo *); |
|
| 3111 havenewmail = va_arg(ap, int); |
|
| 3112 alertitle = va_arg(ap, char *); |
|
| 3113 alerturl = va_arg(ap, char *); |
|
| 3114 va_end(ap); |
|
| 3115 |
|
| 3116 if ((emailinfo != NULL) && gaim_account_get_check_mail(gc->account)) { |
|
| 3117 gchar *to = g_strdup_printf("%s%s%s", gaim_account_get_username(gaim_connection_get_account(gc)), |
|
| 3118 emailinfo->domain ? "@" : "", |
|
| 3119 emailinfo->domain ? emailinfo->domain : ""); |
|
| 3120 if (emailinfo->unread && havenewmail) |
|
| 3121 gaim_notify_emails(gc, emailinfo->nummsgs, FALSE, NULL, NULL, (const char **)&to, (const char **)&emailinfo->url, NULL, NULL); |
|
| 3122 g_free(to); |
|
| 3123 } |
|
| 3124 |
|
| 3125 if (alertitle) |
|
| 3126 gaim_debug_misc("oscar", "Got an alert '%s' %s\n", alertitle, alerturl ? alerturl : ""); |
|
| 3127 |
|
| 3128 return 1; |
|
| 3129 } |
|
| 3130 |
|
| 3131 static int gaim_icon_error(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 3132 GaimConnection *gc = od->gc; |
|
| 3133 char *sn; |
|
| 3134 |
|
| 3135 sn = od->requesticon->data; |
|
| 3136 gaim_debug_misc("oscar", "removing %s from hash table\n", sn); |
|
| 3137 od->requesticon = g_slist_remove(od->requesticon, sn); |
|
| 3138 g_free(sn); |
|
| 3139 |
|
| 3140 if (od->icontimer == 0) |
|
| 3141 od->icontimer = gaim_timeout_add(500, gaim_icon_timerfunc, gc); |
|
| 3142 |
|
| 3143 return 1; |
|
| 3144 } |
|
| 3145 |
|
| 3146 static int gaim_icon_parseicon(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 3147 GaimConnection *gc = od->gc; |
|
| 3148 GSList *cur; |
|
| 3149 va_list ap; |
|
| 3150 char *sn; |
|
| 3151 guint8 iconcsumtype, *iconcsum, *icon; |
|
| 3152 guint16 iconcsumlen, iconlen; |
|
| 3153 |
|
| 3154 va_start(ap, fr); |
|
| 3155 sn = va_arg(ap, char *); |
|
| 3156 iconcsumtype = va_arg(ap, int); |
|
| 3157 iconcsum = va_arg(ap, guint8 *); |
|
| 3158 iconcsumlen = va_arg(ap, int); |
|
| 3159 icon = va_arg(ap, guint8 *); |
|
| 3160 iconlen = va_arg(ap, int); |
|
| 3161 va_end(ap); |
|
| 3162 |
|
| 3163 /* |
|
| 3164 * Some AIM clients will send a blank GIF image with iconlen 90 when |
|
| 3165 * no icon is set. Ignore these. |
|
| 3166 */ |
|
| 3167 if ((iconlen > 0) && (iconlen != 90)) { |
|
| 3168 char *b16; |
|
| 3169 GaimBuddy *b; |
|
| 3170 gaim_buddy_icons_set_for_user(gaim_connection_get_account(gc), |
|
| 3171 sn, icon, iconlen); |
|
| 3172 b16 = gaim_base16_encode(iconcsum, iconcsumlen); |
|
| 3173 b = gaim_find_buddy(gc->account, sn); |
|
| 3174 if ((b16 != NULL) && (b != NULL)) { |
|
| 3175 gaim_blist_node_set_string((GaimBlistNode*)b, "icon_checksum", b16); |
|
| 3176 g_free(b16); |
|
| 3177 } |
|
| 3178 } |
|
| 3179 |
|
| 3180 cur = od->requesticon; |
|
| 3181 while (cur) { |
|
| 3182 char *cursn = cur->data; |
|
| 3183 if (!aim_sncmp(cursn, sn)) { |
|
| 3184 od->requesticon = g_slist_remove(od->requesticon, cursn); |
|
| 3185 g_free(cursn); |
|
| 3186 cur = od->requesticon; |
|
| 3187 } else |
|
| 3188 cur = cur->next; |
|
| 3189 } |
|
| 3190 |
|
| 3191 if (od->icontimer == 0) |
|
| 3192 od->icontimer = gaim_timeout_add(250, gaim_icon_timerfunc, gc); |
|
| 3193 |
|
| 3194 return 1; |
|
| 3195 } |
|
| 3196 |
|
| 3197 static gboolean gaim_icon_timerfunc(gpointer data) { |
|
| 3198 GaimConnection *gc = data; |
|
| 3199 OscarData *od = gc->proto_data; |
|
| 3200 aim_userinfo_t *userinfo; |
|
| 3201 FlapConnection *conn; |
|
| 3202 |
|
| 3203 od->icontimer = 0; |
|
| 3204 |
|
| 3205 conn = flap_connection_getbytype(od, SNAC_FAMILY_BART); |
|
| 3206 if (!conn) { |
|
| 3207 if (!od->iconconnecting) { |
|
| 3208 aim_reqservice(od, SNAC_FAMILY_BART); |
|
| 3209 od->iconconnecting = TRUE; |
|
| 3210 } |
|
| 3211 return FALSE; |
|
| 3212 } |
|
| 3213 |
|
| 3214 if (od->set_icon) { |
|
| 3215 struct stat st; |
|
| 3216 char *iconfile = gaim_buddy_icons_get_full_path(gaim_account_get_buddy_icon(gaim_connection_get_account(gc))); |
|
| 3217 if (iconfile == NULL) { |
|
| 3218 aim_ssi_delicon(od); |
|
| 3219 } else if (!g_stat(iconfile, &st)) { |
|
| 3220 guchar *buf = g_malloc(st.st_size); |
|
| 3221 FILE *file = g_fopen(iconfile, "rb"); |
|
| 3222 if (file) { |
|
| 3223 /* XXX - Use g_file_get_contents()? */ |
|
| 3224 fread(buf, 1, st.st_size, file); |
|
| 3225 fclose(file); |
|
| 3226 gaim_debug_info("oscar", |
|
| 3227 "Uploading icon to icon server\n"); |
|
| 3228 aim_bart_upload(od, buf, st.st_size); |
|
| 3229 } else |
|
| 3230 gaim_debug_error("oscar", |
|
| 3231 "Can't open buddy icon file!\n"); |
|
| 3232 g_free(buf); |
|
| 3233 } else { |
|
| 3234 gaim_debug_error("oscar", |
|
| 3235 "Can't stat buddy icon file!\n"); |
|
| 3236 } |
|
| 3237 g_free(iconfile); |
|
| 3238 od->set_icon = FALSE; |
|
| 3239 } |
|
| 3240 |
|
| 3241 if (!od->requesticon) { |
|
| 3242 gaim_debug_misc("oscar", |
|
| 3243 "no more icons to request\n"); |
|
| 3244 return FALSE; |
|
| 3245 } |
|
| 3246 |
|
| 3247 userinfo = aim_locate_finduserinfo(od, (char *)od->requesticon->data); |
|
| 3248 if ((userinfo != NULL) && (userinfo->iconcsumlen > 0)) { |
|
| 3249 aim_bart_request(od, od->requesticon->data, userinfo->iconcsumtype, userinfo->iconcsum, userinfo->iconcsumlen); |
|
| 3250 return FALSE; |
|
| 3251 } else { |
|
| 3252 gchar *sn = od->requesticon->data; |
|
| 3253 od->requesticon = g_slist_remove(od->requesticon, sn); |
|
| 3254 g_free(sn); |
|
| 3255 } |
|
| 3256 |
|
| 3257 od->icontimer = gaim_timeout_add(100, gaim_icon_timerfunc, gc); |
|
| 3258 |
|
| 3259 return FALSE; |
|
| 3260 } |
|
| 3261 |
|
| 3262 /* |
|
| 3263 * Recieved in response to an IM sent with the AIM_IMFLAGS_ACK option. |
|
| 3264 */ |
|
| 3265 static int gaim_parse_msgack(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 3266 va_list ap; |
|
| 3267 guint16 type; |
|
| 3268 char *sn; |
|
| 3269 |
|
| 3270 va_start(ap, fr); |
|
| 3271 type = (guint16) va_arg(ap, unsigned int); |
|
| 3272 sn = va_arg(ap, char *); |
|
| 3273 va_end(ap); |
|
| 3274 |
|
| 3275 gaim_debug_info("oscar", "Sent message to %s.\n", sn); |
|
| 3276 |
|
| 3277 return 1; |
|
| 3278 } |
|
| 3279 |
|
| 3280 static int gaim_parse_ratechange(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 3281 static const char *codes[5] = { |
|
| 3282 "invalid", |
|
| 3283 "change", |
|
| 3284 "warning", |
|
| 3285 "limit", |
|
| 3286 "limit cleared", |
|
| 3287 }; |
|
| 3288 va_list ap; |
|
| 3289 guint16 code, rateclass; |
|
| 3290 guint32 windowsize, clear, alert, limit, disconnect, currentavg, maxavg; |
|
| 3291 |
|
| 3292 va_start(ap, fr); |
|
| 3293 code = (guint16)va_arg(ap, unsigned int); |
|
| 3294 rateclass= (guint16)va_arg(ap, unsigned int); |
|
| 3295 windowsize = va_arg(ap, guint32); |
|
| 3296 clear = va_arg(ap, guint32); |
|
| 3297 alert = va_arg(ap, guint32); |
|
| 3298 limit = va_arg(ap, guint32); |
|
| 3299 disconnect = va_arg(ap, guint32); |
|
| 3300 currentavg = va_arg(ap, guint32); |
|
| 3301 maxavg = va_arg(ap, guint32); |
|
| 3302 va_end(ap); |
|
| 3303 |
|
| 3304 gaim_debug_misc("oscar", |
|
| 3305 "rate %s (param ID 0x%04hx): curavg = %u, maxavg = %u, alert at %u, " |
|
| 3306 "clear warning at %u, limit at %u, disconnect at %u (window size = %u)\n", |
|
| 3307 (code < 5) ? codes[code] : codes[0], |
|
| 3308 rateclass, |
|
| 3309 currentavg, maxavg, |
|
| 3310 alert, clear, |
|
| 3311 limit, disconnect, |
|
| 3312 windowsize); |
|
| 3313 |
|
| 3314 if (code == AIM_RATE_CODE_LIMIT) |
|
| 3315 { |
|
| 3316 gaim_notify_error(od->gc, NULL, _("Rate limiting error."), |
|
| 3317 _("The last action you attempted could not be " |
|
| 3318 "performed because you are over the rate limit. " |
|
| 3319 "Please wait 10 seconds and try again.")); |
|
| 3320 } |
|
| 3321 |
|
| 3322 return 1; |
|
| 3323 } |
|
| 3324 |
|
| 3325 static int gaim_parse_evilnotify(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 3326 #ifdef CRAZY_WARNING |
|
| 3327 va_list ap; |
|
| 3328 guint16 newevil; |
|
| 3329 aim_userinfo_t *userinfo; |
|
| 3330 |
|
| 3331 va_start(ap, fr); |
|
| 3332 newevil = (guint16) va_arg(ap, unsigned int); |
|
| 3333 userinfo = va_arg(ap, aim_userinfo_t *); |
|
| 3334 va_end(ap); |
|
| 3335 |
|
| 3336 gaim_prpl_got_account_warning_level(account, (userinfo && userinfo->sn) ? userinfo->sn : NULL, (newevil/10.0) + 0.5); |
|
| 3337 #endif |
|
| 3338 |
|
| 3339 return 1; |
|
| 3340 } |
|
| 3341 |
|
| 3342 static int gaim_selfinfo(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 3343 int warning_level; |
|
| 3344 va_list ap; |
|
| 3345 aim_userinfo_t *info; |
|
| 3346 |
|
| 3347 va_start(ap, fr); |
|
| 3348 info = va_arg(ap, aim_userinfo_t *); |
|
| 3349 va_end(ap); |
|
| 3350 |
|
| 3351 /* |
|
| 3352 * What's with the + 0.5? |
|
| 3353 * The 0.5 is basically poor-man's rounding. Normally |
|
| 3354 * casting "13.7" to an int will truncate to "13," but |
|
| 3355 * with 13.7 + 0.5 = 14.2, which becomes "14" when |
|
| 3356 * truncated. |
|
| 3357 */ |
|
| 3358 warning_level = info->warnlevel/10.0 + 0.5; |
|
| 3359 |
|
| 3360 #ifdef CRAZY_WARNING |
|
| 3361 gaim_presence_set_warning_level(presence, warning_level); |
|
| 3362 #endif |
|
| 3363 |
|
| 3364 return 1; |
|
| 3365 } |
|
| 3366 |
|
| 3367 static int gaim_connerr(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 3368 GaimConnection *gc = od->gc; |
|
| 3369 va_list ap; |
|
| 3370 guint16 code; |
|
| 3371 char *msg; |
|
| 3372 |
|
| 3373 va_start(ap, fr); |
|
| 3374 code = (guint16)va_arg(ap, int); |
|
| 3375 msg = va_arg(ap, char *); |
|
| 3376 va_end(ap); |
|
| 3377 |
|
| 3378 gaim_debug_info("oscar", "Disconnected. Code is 0x%04x and msg is %s\n", |
|
| 3379 code, (msg != NULL ? msg : "")); |
|
| 3380 |
|
| 3381 g_return_val_if_fail(fr != NULL, 1); |
|
| 3382 g_return_val_if_fail(conn != NULL, 1); |
|
| 3383 |
|
| 3384 if (conn->type == SNAC_FAMILY_LOCATE) { |
|
| 3385 if (code == 0x0001) { |
|
| 3386 gc->wants_to_die = TRUE; |
|
| 3387 gaim_connection_error(gc, _("You have signed on from another location.")); |
|
| 3388 } else { |
|
| 3389 gaim_connection_error(gc, _("You have been signed off for an unknown reason.")); |
|
| 3390 } |
|
| 3391 od->killme = TRUE; |
|
| 3392 } else if (conn->type == SNAC_FAMILY_CHAT) { |
|
| 3393 struct chat_connection *cc; |
|
| 3394 GaimConversation *conv; |
|
| 3395 |
|
| 3396 cc = find_oscar_chat_by_conn(gc, conn); |
|
| 3397 conv = gaim_find_chat(gc, cc->id); |
|
| 3398 |
|
| 3399 if (conv != NULL) |
|
| 3400 { |
|
| 3401 gchar *buf; |
|
| 3402 buf = g_strdup_printf(_("You have been disconnected from chat " |
|
| 3403 "room %s."), cc->name); |
|
| 3404 gaim_conversation_write(conv, NULL, buf, GAIM_MESSAGE_ERROR, time(NULL)); |
|
| 3405 g_free(buf); |
|
| 3406 } |
|
| 3407 oscar_chat_kill(gc, cc); |
|
| 3408 } |
|
| 3409 |
|
| 3410 return 1; |
|
| 3411 } |
|
| 3412 |
|
| 3413 static int gaim_icbm_param_info(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 3414 struct aim_icbmparameters *params; |
|
| 3415 va_list ap; |
|
| 3416 |
|
| 3417 va_start(ap, fr); |
|
| 3418 params = va_arg(ap, struct aim_icbmparameters *); |
|
| 3419 va_end(ap); |
|
| 3420 |
|
| 3421 /* XXX - evidently this crashes on solaris. i have no clue why |
|
| 3422 gaim_debug_misc("oscar", "ICBM Parameters: maxchannel = %hu, default flags = 0x%08lx, max msg len = %hu, " |
|
| 3423 "max sender evil = %f, max receiver evil = %f, min msg interval = %u\n", |
|
| 3424 params->maxchan, params->flags, params->maxmsglen, |
|
| 3425 ((float)params->maxsenderwarn)/10.0, ((float)params->maxrecverwarn)/10.0, |
|
| 3426 params->minmsginterval); |
|
| 3427 */ |
|
| 3428 |
|
| 3429 /* Maybe senderwarn and recverwarn should be user preferences... */ |
|
| 3430 params->flags = 0x0000000b; |
|
| 3431 params->maxmsglen = 8000; |
|
| 3432 params->minmsginterval = 0; |
|
| 3433 |
|
| 3434 aim_im_setparams(od, params); |
|
| 3435 |
|
| 3436 return 1; |
|
| 3437 } |
|
| 3438 |
|
| 3439 static int gaim_parse_locaterights(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) |
|
| 3440 { |
|
| 3441 GaimConnection *gc = od->gc; |
|
| 3442 GaimAccount *account = gaim_connection_get_account(gc); |
|
| 3443 va_list ap; |
|
| 3444 guint16 maxsiglen; |
|
| 3445 |
|
| 3446 va_start(ap, fr); |
|
| 3447 maxsiglen = (guint16) va_arg(ap, int); |
|
| 3448 va_end(ap); |
|
| 3449 |
|
| 3450 gaim_debug_misc("oscar", |
|
| 3451 "locate rights: max sig len = %d\n", maxsiglen); |
|
| 3452 |
|
| 3453 od->rights.maxsiglen = od->rights.maxawaymsglen = (guint)maxsiglen; |
|
| 3454 |
|
| 3455 if (od->icq) |
|
| 3456 aim_locate_setcaps(od, caps_icq); |
|
| 3457 else |
|
| 3458 aim_locate_setcaps(od, caps_aim); |
|
| 3459 oscar_set_info_and_status(account, TRUE, account->user_info, TRUE, |
|
| 3460 gaim_account_get_active_status(account)); |
|
| 3461 |
|
| 3462 return 1; |
|
| 3463 } |
|
| 3464 |
|
| 3465 static int gaim_parse_buddyrights(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 3466 va_list ap; |
|
| 3467 guint16 maxbuddies, maxwatchers; |
|
| 3468 |
|
| 3469 va_start(ap, fr); |
|
| 3470 maxbuddies = (guint16) va_arg(ap, unsigned int); |
|
| 3471 maxwatchers = (guint16) va_arg(ap, unsigned int); |
|
| 3472 va_end(ap); |
|
| 3473 |
|
| 3474 gaim_debug_misc("oscar", |
|
| 3475 "buddy list rights: Max buddies = %hu / Max watchers = %hu\n", maxbuddies, maxwatchers); |
|
| 3476 |
|
| 3477 od->rights.maxbuddies = (guint)maxbuddies; |
|
| 3478 od->rights.maxwatchers = (guint)maxwatchers; |
|
| 3479 |
|
| 3480 return 1; |
|
| 3481 } |
|
| 3482 |
|
| 3483 static int gaim_bosrights(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 3484 GaimConnection *gc; |
|
| 3485 GaimAccount *account; |
|
| 3486 GaimStatus *status; |
|
| 3487 const char *message; |
|
| 3488 char *tmp; |
|
| 3489 va_list ap; |
|
| 3490 guint16 maxpermits, maxdenies; |
|
| 3491 |
|
| 3492 gc = od->gc; |
|
| 3493 od = (OscarData *)gc->proto_data; |
|
| 3494 account = gaim_connection_get_account(gc); |
|
| 3495 |
|
| 3496 va_start(ap, fr); |
|
| 3497 maxpermits = (guint16) va_arg(ap, unsigned int); |
|
| 3498 maxdenies = (guint16) va_arg(ap, unsigned int); |
|
| 3499 va_end(ap); |
|
| 3500 |
|
| 3501 gaim_debug_misc("oscar", |
|
| 3502 "BOS rights: Max permit = %hu / Max deny = %hu\n", maxpermits, maxdenies); |
|
| 3503 |
|
| 3504 od->rights.maxpermits = (guint)maxpermits; |
|
| 3505 od->rights.maxdenies = (guint)maxdenies; |
|
| 3506 |
|
| 3507 gaim_connection_set_state(gc, GAIM_CONNECTED); |
|
| 3508 |
|
| 3509 gaim_debug_info("oscar", "buddy list loaded\n"); |
|
| 3510 |
|
| 3511 aim_clientready(od, conn); |
|
| 3512 |
|
| 3513 /* Set our available message based on the current status */ |
|
| 3514 status = gaim_account_get_active_status(account); |
|
| 3515 if (gaim_status_is_available(status)) |
|
| 3516 message = gaim_status_get_attr_string(status, "message"); |
|
| 3517 else |
|
| 3518 message = NULL; |
|
| 3519 tmp = gaim_markup_strip_html(message); |
|
| 3520 aim_srv_setstatusmsg(od, tmp); |
|
| 3521 g_free(tmp); |
|
| 3522 |
|
| 3523 aim_srv_setidle(od, 0); |
|
| 3524 |
|
| 3525 if (od->icq) { |
|
| 3526 aim_icq_reqofflinemsgs(od); |
|
| 3527 oscar_set_extendedstatus(gc); |
|
| 3528 aim_icq_setsecurity(od, |
|
| 3529 gaim_account_get_bool(account, "authorization", OSCAR_DEFAULT_AUTHORIZATION), |
|
| 3530 gaim_account_get_bool(account, "web_aware", OSCAR_DEFAULT_WEB_AWARE)); |
|
| 3531 } |
|
| 3532 |
|
| 3533 aim_reqservice(od, SNAC_FAMILY_CHATNAV); |
|
| 3534 if (od->authinfo->email != NULL) |
|
| 3535 aim_reqservice(od, SNAC_FAMILY_ALERT); |
|
| 3536 |
|
| 3537 return 1; |
|
| 3538 } |
|
| 3539 |
|
| 3540 static int gaim_offlinemsg(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 3541 va_list ap; |
|
| 3542 struct aim_icq_offlinemsg *msg; |
|
| 3543 struct aim_incomingim_ch4_args args; |
|
| 3544 time_t t; |
|
| 3545 |
|
| 3546 va_start(ap, fr); |
|
| 3547 msg = va_arg(ap, struct aim_icq_offlinemsg *); |
|
| 3548 va_end(ap); |
|
| 3549 |
|
| 3550 gaim_debug_info("oscar", |
|
| 3551 "Received offline message. Converting to channel 4 ICBM...\n"); |
|
| 3552 args.uin = msg->sender; |
|
| 3553 args.type = msg->type; |
|
| 3554 args.flags = msg->flags; |
|
| 3555 args.msglen = msg->msglen; |
|
| 3556 args.msg = msg->msg; |
|
| 3557 t = gaim_time_build(msg->year, msg->month, msg->day, msg->hour, msg->minute, 0); |
|
| 3558 incomingim_chan4(od, conn, NULL, &args, t); |
|
| 3559 |
|
| 3560 return 1; |
|
| 3561 } |
|
| 3562 |
|
| 3563 static int gaim_offlinemsgdone(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) |
|
| 3564 { |
|
| 3565 aim_icq_ackofflinemsgs(od); |
|
| 3566 return 1; |
|
| 3567 } |
|
| 3568 |
|
| 3569 static int gaim_icqinfo(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) |
|
| 3570 { |
|
| 3571 GaimConnection *gc; |
|
| 3572 GaimAccount *account; |
|
| 3573 GaimBuddy *buddy; |
|
| 3574 struct buddyinfo *bi; |
|
| 3575 gchar who[16]; |
|
| 3576 GString *str; |
|
| 3577 gchar *utf8; |
|
| 3578 const gchar *alias; |
|
| 3579 va_list ap; |
|
| 3580 struct aim_icq_info *info; |
|
| 3581 |
|
| 3582 gc = od->gc; |
|
| 3583 account = gaim_connection_get_account(gc); |
|
| 3584 |
|
| 3585 va_start(ap, fr); |
|
| 3586 info = va_arg(ap, struct aim_icq_info *); |
|
| 3587 va_end(ap); |
|
| 3588 |
|
| 3589 if (!info->uin) |
|
| 3590 return 0; |
|
| 3591 |
|
| 3592 str = g_string_sized_new(100); |
|
| 3593 g_snprintf(who, sizeof(who), "%u", info->uin); |
|
| 3594 buddy = gaim_find_buddy(gaim_connection_get_account(gc), who); |
|
| 3595 if (buddy != NULL) |
|
| 3596 bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(buddy->account, buddy->name)); |
|
| 3597 else |
|
| 3598 bi = NULL; |
|
| 3599 |
|
| 3600 g_string_append_printf(str, "<b>%s:</b> %s", _("UIN"), who); |
|
| 3601 oscar_string_convert_and_append(account, str, "\n<br>", _("Nick"), info->nick); |
|
| 3602 if ((bi != NULL) && (bi->ipaddr != 0)) { |
|
| 3603 char *tstr = g_strdup_printf("%hhu.%hhu.%hhu.%hhu", |
|
| 3604 (bi->ipaddr & 0xff000000) >> 24, |
|
| 3605 (bi->ipaddr & 0x00ff0000) >> 16, |
|
| 3606 (bi->ipaddr & 0x0000ff00) >> 8, |
|
| 3607 (bi->ipaddr & 0x000000ff)); |
|
| 3608 oscar_string_append(str, "\n<br>", _("IP Address"), tstr); |
|
| 3609 g_free(tstr); |
|
| 3610 } |
|
| 3611 oscar_string_convert_and_append(account, str, "\n<br>", _("First Name"), info->first); |
|
| 3612 oscar_string_convert_and_append(account, str, "\n<br>", _("Last Name"), info->last); |
|
| 3613 if (info->email && info->email[0] && (utf8 = oscar_utf8_try_convert(gc->account, info->email))) { |
|
| 3614 g_string_append_printf(str, "\n<br><b>%s:</b> <a href=\"mailto:%s\">%s</a>", _("E-Mail Address"), utf8, utf8); |
|
| 3615 g_free(utf8); |
|
| 3616 } |
|
| 3617 if (info->numaddresses && info->email2) { |
|
| 3618 int i; |
|
| 3619 for (i = 0; i < info->numaddresses; i++) { |
|
| 3620 if (info->email2[i] && info->email2[i][0] && (utf8 = oscar_utf8_try_convert(gc->account, info->email2[i]))) { |
|
| 3621 g_string_append_printf(str, "\n<br><b>%s:</b> <a href=\"mailto:%s\">%s</a>", _("E-Mail Address"), utf8, utf8); |
|
| 3622 g_free(utf8); |
|
| 3623 } |
|
| 3624 } |
|
| 3625 } |
|
| 3626 oscar_string_convert_and_append(account, str, "\n<br>", _("Mobile Phone"), info->mobile); |
|
| 3627 if (info->gender != 0) |
|
| 3628 oscar_string_append(str, "\n<br>", _("Gender"), info->gender == 1 ? _("Female") : _("Male")); |
|
| 3629 if ((info->birthyear > 1900) && (info->birthmonth > 0) && (info->birthday > 0)) { |
|
| 3630 /* Initialize the struct properly or strftime() will crash |
|
| 3631 * under some conditions (e.g. Debian sarge w/ LANG=en_HK). */ |
|
| 3632 time_t t = time(NULL); |
|
| 3633 struct tm *tm = localtime(&t); |
|
| 3634 |
|
| 3635 tm->tm_mday = (int)info->birthday; |
|
| 3636 tm->tm_mon = (int)info->birthmonth - 1; |
|
| 3637 tm->tm_year = (int)info->birthyear - 1900; |
|
| 3638 |
|
| 3639 /* To be 100% sure that the fields are re-normalized. |
|
| 3640 * If you're sure strftime() ALWAYS does this EVERYWHERE, |
|
| 3641 * feel free to remove it. --rlaager */ |
|
| 3642 mktime(tm); |
|
| 3643 |
|
| 3644 oscar_string_append(str, "\n<br>", _("Birthday"), |
|
| 3645 gaim_date_format_short(tm)); |
|
| 3646 } |
|
| 3647 if ((info->age > 0) && (info->age < 255)) { |
|
| 3648 char age[5]; |
|
| 3649 snprintf(age, sizeof(age), "%hhd", info->age); |
|
| 3650 oscar_string_append(str, "\n<br>", _("Age"), age); |
|
| 3651 } |
|
| 3652 if (info->personalwebpage && info->personalwebpage[0] && (utf8 = oscar_utf8_try_convert(gc->account, info->personalwebpage))) { |
|
| 3653 g_string_append_printf(str, "\n<br><b>%s:</b> <a href=\"%s\">%s</a>", _("Personal Web Page"), utf8, utf8); |
|
| 3654 g_free(utf8); |
|
| 3655 } |
|
| 3656 if (info->info && info->info[0] && (utf8 = oscar_utf8_try_convert(gc->account, info->info))) { |
|
| 3657 g_string_append_printf(str, "<hr><b>%s:</b><br>%s", _("Additional Information"), utf8); |
|
| 3658 g_free(utf8); |
|
| 3659 } |
|
| 3660 g_string_append_printf(str, "<hr>"); |
|
| 3661 if ((info->homeaddr && (info->homeaddr[0])) || (info->homecity && info->homecity[0]) || (info->homestate && info->homestate[0]) || (info->homezip && info->homezip[0])) { |
|
| 3662 g_string_append_printf(str, "<b>%s:</b>", _("Home Address")); |
|
| 3663 oscar_string_convert_and_append(account, str, "\n<br>", _("Address"), info->homeaddr); |
|
| 3664 oscar_string_convert_and_append(account, str, "\n<br>", _("City"), info->homecity); |
|
| 3665 oscar_string_convert_and_append(account, str, "\n<br>", _("State"), info->homestate); |
|
| 3666 oscar_string_convert_and_append(account, str, "\n<br>", _("Zip Code"), info->homezip); |
|
| 3667 g_string_append_printf(str, "\n<hr>"); |
|
| 3668 } |
|
| 3669 if ((info->workaddr && info->workaddr[0]) || (info->workcity && info->workcity[0]) || (info->workstate && info->workstate[0]) || (info->workzip && info->workzip[0])) { |
|
| 3670 g_string_append_printf(str, "<b>%s:</b>", _("Work Address")); |
|
| 3671 oscar_string_convert_and_append(account, str, "\n<br>", _("Address"), info->workaddr); |
|
| 3672 oscar_string_convert_and_append(account, str, "\n<br>", _("City"), info->workcity); |
|
| 3673 oscar_string_convert_and_append(account, str, "\n<br>", _("State"), info->workstate); |
|
| 3674 oscar_string_convert_and_append(account, str, "\n<br>", _("Zip Code"), info->workzip); |
|
| 3675 g_string_append_printf(str, "\n<hr>"); |
|
| 3676 } |
|
| 3677 if ((info->workcompany && info->workcompany[0]) || (info->workdivision && info->workdivision[0]) || (info->workposition && info->workposition[0]) || (info->workwebpage && info->workwebpage[0])) { |
|
| 3678 g_string_append_printf(str, "<b>%s:</b>", _("Work Information")); |
|
| 3679 oscar_string_convert_and_append(account, str, "\n<br>", _("Company"), info->workcompany); |
|
| 3680 oscar_string_convert_and_append(account, str, "\n<br>", _("Division"), info->workdivision); |
|
| 3681 oscar_string_convert_and_append(account, str, "\n<br>", _("Position"), info->workposition); |
|
| 3682 if (info->workwebpage && info->workwebpage[0] && (utf8 = oscar_utf8_try_convert(gc->account, info->workwebpage))) { |
|
| 3683 g_string_append_printf(str, "\n<br><b>%s:</b> <a href=\"%s\">%s</a>", _("Web Page"), utf8, utf8); |
|
| 3684 g_free(utf8); |
|
| 3685 } |
|
| 3686 g_string_append_printf(str, "\n<hr>"); |
|
| 3687 } |
|
| 3688 |
|
| 3689 if (buddy != NULL) |
|
| 3690 alias = gaim_buddy_get_alias(buddy); |
|
| 3691 else |
|
| 3692 alias = who; |
|
| 3693 gaim_notify_userinfo(gc, who, str->str, NULL, NULL); |
|
| 3694 g_string_free(str, TRUE); |
|
| 3695 |
|
| 3696 return 1; |
|
| 3697 } |
|
| 3698 |
|
| 3699 static int gaim_icqalias(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) |
|
| 3700 { |
|
| 3701 GaimConnection *gc = od->gc; |
|
| 3702 GaimAccount *account = gaim_connection_get_account(gc); |
|
| 3703 gchar who[16], *utf8; |
|
| 3704 GaimBuddy *b; |
|
| 3705 va_list ap; |
|
| 3706 struct aim_icq_info *info; |
|
| 3707 |
|
| 3708 va_start(ap, fr); |
|
| 3709 info = va_arg(ap, struct aim_icq_info *); |
|
| 3710 va_end(ap); |
|
| 3711 |
|
| 3712 if (info->uin && info->nick && info->nick[0] && (utf8 = oscar_utf8_try_convert(account, info->nick))) { |
|
| 3713 g_snprintf(who, sizeof(who), "%u", info->uin); |
|
| 3714 serv_got_alias(gc, who, utf8); |
|
| 3715 if ((b = gaim_find_buddy(gc->account, who))) { |
|
| 3716 gaim_blist_node_set_string((GaimBlistNode*)b, "servernick", utf8); |
|
| 3717 } |
|
| 3718 g_free(utf8); |
|
| 3719 } |
|
| 3720 |
|
| 3721 return 1; |
|
| 3722 } |
|
| 3723 |
|
| 3724 static int gaim_popup(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) |
|
| 3725 { |
|
| 3726 GaimConnection *gc = od->gc; |
|
| 3727 gchar *text; |
|
| 3728 va_list ap; |
|
| 3729 char *msg, *url; |
|
| 3730 guint16 wid, hei, delay; |
|
| 3731 |
|
| 3732 va_start(ap, fr); |
|
| 3733 msg = va_arg(ap, char *); |
|
| 3734 url = va_arg(ap, char *); |
|
| 3735 wid = (guint16) va_arg(ap, int); |
|
| 3736 hei = (guint16) va_arg(ap, int); |
|
| 3737 delay = (guint16) va_arg(ap, int); |
|
| 3738 va_end(ap); |
|
| 3739 |
|
| 3740 text = g_strdup_printf("%s<br><a href=\"%s\">%s</a>", msg, url, url); |
|
| 3741 gaim_notify_formatted(gc, NULL, _("Pop-Up Message"), NULL, text, NULL, NULL); |
|
| 3742 g_free(text); |
|
| 3743 |
|
| 3744 return 1; |
|
| 3745 } |
|
| 3746 |
|
| 3747 static void oscar_searchresults_add_buddy_cb(GaimConnection *gc, GList *row, void *user_data) |
|
| 3748 { |
|
| 3749 gaim_blist_request_add_buddy(gaim_connection_get_account(gc), |
|
| 3750 g_list_nth_data(row, 0), NULL, NULL); |
|
| 3751 } |
|
| 3752 |
|
| 3753 static int gaim_parse_searchreply(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) |
|
| 3754 { |
|
| 3755 GaimConnection *gc = od->gc; |
|
| 3756 GaimNotifySearchResults *results; |
|
| 3757 GaimNotifySearchColumn *column; |
|
| 3758 gchar *secondary; |
|
| 3759 int i, num; |
|
| 3760 va_list ap; |
|
| 3761 char *email, *SNs; |
|
| 3762 |
|
| 3763 va_start(ap, fr); |
|
| 3764 email = va_arg(ap, char *); |
|
| 3765 num = va_arg(ap, int); |
|
| 3766 SNs = va_arg(ap, char *); |
|
| 3767 va_end(ap); |
|
| 3768 |
|
| 3769 results = gaim_notify_searchresults_new(); |
|
| 3770 |
|
| 3771 if (results == NULL) { |
|
| 3772 gaim_debug_error("oscar", "gaim_parse_searchreply: " |
|
| 3773 "Unable to display the search results.\n"); |
|
| 3774 gaim_notify_error(gc, NULL, |
|
| 3775 _("Unable to display the search results."), |
|
| 3776 NULL); |
|
| 3777 return 1; |
|
| 3778 } |
|
| 3779 |
|
| 3780 secondary = g_strdup_printf( |
|
| 3781 ngettext("The following screen name is associated with %s", |
|
| 3782 "The following screen names are associated with %s", |
|
| 3783 num), |
|
| 3784 email); |
|
| 3785 |
|
| 3786 column = gaim_notify_searchresults_column_new(_("Screen name")); |
|
| 3787 gaim_notify_searchresults_column_add(results, column); |
|
| 3788 |
|
| 3789 for (i = 0; i < num; i++) { |
|
| 3790 GList *row = NULL; |
|
| 3791 row = g_list_append(row, g_strdup(&SNs[i * (MAXSNLEN + 1)])); |
|
| 3792 gaim_notify_searchresults_row_add(results, row); |
|
| 3793 } |
|
| 3794 gaim_notify_searchresults_button_add(results, GAIM_NOTIFY_BUTTON_ADD, |
|
| 3795 oscar_searchresults_add_buddy_cb); |
|
| 3796 gaim_notify_searchresults(gc, NULL, NULL, secondary, results, NULL, NULL); |
|
| 3797 |
|
| 3798 g_free(secondary); |
|
| 3799 |
|
| 3800 return 1; |
|
| 3801 } |
|
| 3802 |
|
| 3803 static int gaim_parse_searcherror(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 3804 va_list ap; |
|
| 3805 char *email; |
|
| 3806 char *buf; |
|
| 3807 |
|
| 3808 va_start(ap, fr); |
|
| 3809 email = va_arg(ap, char *); |
|
| 3810 va_end(ap); |
|
| 3811 |
|
| 3812 buf = g_strdup_printf(_("No results found for e-mail address %s"), email); |
|
| 3813 gaim_notify_error(od->gc, NULL, buf, NULL); |
|
| 3814 g_free(buf); |
|
| 3815 |
|
| 3816 return 1; |
|
| 3817 } |
|
| 3818 |
|
| 3819 static int gaim_account_confirm(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 3820 GaimConnection *gc = od->gc; |
|
| 3821 guint16 status; |
|
| 3822 va_list ap; |
|
| 3823 char msg[256]; |
|
| 3824 |
|
| 3825 va_start(ap, fr); |
|
| 3826 status = (guint16) va_arg(ap, unsigned int); /* status code of confirmation request */ |
|
| 3827 va_end(ap); |
|
| 3828 |
|
| 3829 gaim_debug_info("oscar", |
|
| 3830 "account confirmation returned status 0x%04x (%s)\n", status, |
|
| 3831 status ? "unknown" : "e-mail sent"); |
|
| 3832 if (!status) { |
|
| 3833 g_snprintf(msg, sizeof(msg), _("You should receive an e-mail asking to confirm %s."), |
|
| 3834 gaim_account_get_username(gaim_connection_get_account(gc))); |
|
| 3835 gaim_notify_info(gc, NULL, _("Account Confirmation Requested"), msg); |
|
| 3836 } |
|
| 3837 |
|
| 3838 return 1; |
|
| 3839 } |
|
| 3840 |
|
| 3841 static int gaim_info_change(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 3842 GaimConnection *gc = od->gc; |
|
| 3843 va_list ap; |
|
| 3844 guint16 perms, err; |
|
| 3845 char *url, *sn, *email; |
|
| 3846 int change; |
|
| 3847 |
|
| 3848 va_start(ap, fr); |
|
| 3849 change = va_arg(ap, int); |
|
| 3850 perms = (guint16) va_arg(ap, unsigned int); |
|
| 3851 err = (guint16) va_arg(ap, unsigned int); |
|
| 3852 url = va_arg(ap, char *); |
|
| 3853 sn = va_arg(ap, char *); |
|
| 3854 email = va_arg(ap, char *); |
|
| 3855 va_end(ap); |
|
| 3856 |
|
| 3857 gaim_debug_misc("oscar", |
|
| 3858 "account info: because of %s, perms=0x%04x, err=0x%04x, url=%s, sn=%s, email=%s\n", |
|
| 3859 change ? "change" : "request", perms, err, |
|
| 3860 (url != NULL) ? url : "(null)", |
|
| 3861 (sn != NULL) ? sn : "(null)", |
|
| 3862 (email != NULL) ? email : "(null)"); |
|
| 3863 |
|
| 3864 if ((err > 0) && (url != NULL)) { |
|
| 3865 char *dialog_msg; |
|
| 3866 char *dialog_top = g_strdup_printf(_("Error Changing Account Info")); |
|
| 3867 switch (err) { |
|
| 3868 case 0x0001: { |
|
| 3869 dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to format screen name because the requested screen name differs from the original."), err); |
|
| 3870 } break; |
|
| 3871 case 0x0006: { |
|
| 3872 dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to format screen name because it is invalid."), err); |
|
| 3873 } break; |
|
| 3874 case 0x000b: { |
|
| 3875 dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to format screen name because the requested screen name is too long."), err); |
|
| 3876 } break; |
|
| 3877 case 0x001d: { |
|
| 3878 dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to change e-mail address because there is already a request pending for this screen name."), err); |
|
| 3879 } break; |
|
| 3880 case 0x0021: { |
|
| 3881 dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to change e-mail address because the given address has too many screen names associated with it."), err); |
|
| 3882 } break; |
|
| 3883 case 0x0023: { |
|
| 3884 dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to change e-mail address because the given address is invalid."), err); |
|
| 3885 } break; |
|
| 3886 default: { |
|
| 3887 dialog_msg = g_strdup_printf(_("Error 0x%04x: Unknown error."), err); |
|
| 3888 } break; |
|
| 3889 } |
|
| 3890 gaim_notify_error(gc, NULL, dialog_top, dialog_msg); |
|
| 3891 g_free(dialog_top); |
|
| 3892 g_free(dialog_msg); |
|
| 3893 return 1; |
|
| 3894 } |
|
| 3895 |
|
| 3896 if (sn != NULL) { |
|
| 3897 char *dialog_msg = g_strdup_printf(_("Your screen name is currently formatted as follows:\n%s"), sn); |
|
| 3898 gaim_notify_info(gc, NULL, _("Account Info"), dialog_msg); |
|
| 3899 g_free(dialog_msg); |
|
| 3900 } |
|
| 3901 |
|
| 3902 if (email != NULL) { |
|
| 3903 char *dialog_msg = g_strdup_printf(_("The e-mail address for %s is %s"), |
|
| 3904 gaim_account_get_username(gaim_connection_get_account(gc)), email); |
|
| 3905 gaim_notify_info(gc, NULL, _("Account Info"), dialog_msg); |
|
| 3906 g_free(dialog_msg); |
|
| 3907 } |
|
| 3908 |
|
| 3909 return 1; |
|
| 3910 } |
|
| 3911 |
|
| 3912 static void |
|
| 3913 oscar_keepalive(GaimConnection *gc) |
|
| 3914 { |
|
| 3915 OscarData *od; |
|
| 3916 FlapConnection *conn; |
|
| 3917 |
|
| 3918 od = (OscarData *)gc->proto_data; |
|
| 3919 conn = flap_connection_getbytype(od, SNAC_FAMILY_LOCATE); |
|
| 3920 if (conn != NULL) |
|
| 3921 flap_connection_send_keepalive(od, conn); |
|
| 3922 } |
|
| 3923 |
|
| 3924 static unsigned int |
|
| 3925 oscar_send_typing(GaimConnection *gc, const char *name, GaimTypingState state) |
|
| 3926 { |
|
| 3927 OscarData *od; |
|
| 3928 PeerConnection *conn; |
|
| 3929 |
|
| 3930 od = (OscarData *)gc->proto_data; |
|
| 3931 conn = peer_connection_find_by_type(od, name, OSCAR_CAPABILITY_DIRECTIM); |
|
| 3932 |
|
| 3933 if ((conn != NULL) && (conn->ready)) |
|
| 3934 { |
|
| 3935 peer_odc_send_typing(conn, state); |
|
| 3936 } |
|
| 3937 else { |
|
| 3938 /* Don't send if this turkey is in our deny list */ |
|
| 3939 GSList *list; |
|
| 3940 for (list=gc->account->deny; (list && aim_sncmp(name, list->data)); list=list->next); |
|
| 3941 if (!list) { |
|
| 3942 struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(gc->account, name)); |
|
| 3943 if (bi && bi->typingnot) { |
|
| 3944 if (state == GAIM_TYPING) |
|
| 3945 aim_im_sendmtn(od, 0x0001, name, 0x0002); |
|
| 3946 else if (state == GAIM_TYPED) |
|
| 3947 aim_im_sendmtn(od, 0x0001, name, 0x0001); |
|
| 3948 else |
|
| 3949 aim_im_sendmtn(od, 0x0001, name, 0x0000); |
|
| 3950 } |
|
| 3951 } |
|
| 3952 } |
|
| 3953 return 0; |
|
| 3954 } |
|
| 3955 |
|
| 3956 /* TODO: Move this into odc.c! */ |
|
| 3957 static void |
|
| 3958 gaim_odc_send_im(PeerConnection *conn, const char *message, GaimMessageFlags imflags) |
|
| 3959 { |
|
| 3960 GString *msg; |
|
| 3961 GString *data; |
|
| 3962 gchar *tmp; |
|
| 3963 int tmplen; |
|
| 3964 guint16 charset, charsubset; |
|
| 3965 GData *attribs; |
|
| 3966 const char *start, *end, *last; |
|
| 3967 int oscar_id = 0; |
|
| 3968 |
|
| 3969 msg = g_string_new("<HTML><BODY>"); |
|
| 3970 data = g_string_new("<BINARY>"); |
|
| 3971 last = message; |
|
| 3972 |
|
| 3973 /* for each valid IMG tag... */ |
|
| 3974 while (last && *last && gaim_markup_find_tag("img", last, &start, &end, &attribs)) |
|
| 3975 { |
|
| 3976 GaimStoredImage *image = NULL; |
|
| 3977 const char *id; |
|
| 3978 |
|
| 3979 if (start - last) { |
|
| 3980 g_string_append_len(msg, last, start - last); |
|
| 3981 } |
|
| 3982 |
|
| 3983 id = g_datalist_get_data(&attribs, "id"); |
|
| 3984 |
|
| 3985 /* ... if it refers to a valid gaim image ... */ |
|
| 3986 if (id && (image = gaim_imgstore_get(atoi(id)))) { |
|
| 3987 /* ... append the message from start to the tag ... */ |
|
| 3988 unsigned long size = gaim_imgstore_get_size(image); |
|
| 3989 const char *filename = gaim_imgstore_get_filename(image); |
|
| 3990 gpointer imgdata = gaim_imgstore_get_data(image); |
|
| 3991 |
|
| 3992 oscar_id++; |
|
| 3993 |
|
| 3994 /* ... insert a new img tag with the oscar id ... */ |
|
| 3995 if (filename) |
|
| 3996 g_string_append_printf(msg, |
|
| 3997 "<IMG SRC=\"%s\" ID=\"%d\" DATASIZE=\"%lu\">", |
|
| 3998 filename, oscar_id, size); |
|
| 3999 else |
|
| 4000 g_string_append_printf(msg, |
|
| 4001 "<IMG ID=\"%d\" DATASIZE=\"%lu\">", |
|
| 4002 oscar_id, size); |
|
| 4003 |
|
| 4004 /* ... and append the data to the binary section ... */ |
|
| 4005 g_string_append_printf(data, "<DATA ID=\"%d\" SIZE=\"%lu\">", |
|
| 4006 oscar_id, size); |
|
| 4007 g_string_append_len(data, imgdata, size); |
|
| 4008 g_string_append(data, "</DATA>"); |
|
| 4009 } |
|
| 4010 /* If the tag is invalid, skip it, thus no else here */ |
|
| 4011 |
|
| 4012 g_datalist_clear(&attribs); |
|
| 4013 |
|
| 4014 /* continue from the end of the tag */ |
|
| 4015 last = end + 1; |
|
| 4016 } |
|
| 4017 |
|
| 4018 /* append any remaining message data */ |
|
| 4019 if (last && *last) |
|
| 4020 g_string_append(msg, last); |
|
| 4021 |
|
| 4022 g_string_append(msg, "</BODY></HTML>"); |
|
| 4023 |
|
| 4024 /* Convert the message to a good encoding */ |
|
| 4025 gaim_plugin_oscar_convert_to_best_encoding(conn->od->gc, |
|
| 4026 conn->sn, msg->str, &tmp, &tmplen, &charset, &charsubset); |
|
| 4027 g_string_free(msg, TRUE); |
|
| 4028 msg = g_string_new_len(tmp, tmplen); |
|
| 4029 |
|
| 4030 /* Append any binary data that we may have */ |
|
| 4031 if (oscar_id) { |
|
| 4032 msg = g_string_append_len(msg, data->str, data->len); |
|
| 4033 msg = g_string_append(msg, "</BINARY>"); |
|
| 4034 } |
|
| 4035 g_string_free(data, TRUE); |
|
| 4036 |
|
| 4037 peer_odc_send_im(conn, msg->str, msg->len, charset, |
|
| 4038 imflags & GAIM_MESSAGE_AUTO_RESP); |
|
| 4039 g_string_free(msg, TRUE); |
|
| 4040 } |
|
| 4041 |
|
| 4042 static int |
|
| 4043 oscar_send_im(GaimConnection *gc, const char *name, const char *message, GaimMessageFlags imflags) |
|
| 4044 { |
|
| 4045 OscarData *od; |
|
| 4046 GaimAccount *account; |
|
| 4047 PeerConnection *conn; |
|
| 4048 int ret; |
|
| 4049 char *iconfile; |
|
| 4050 char *tmp1, *tmp2; |
|
| 4051 |
|
| 4052 od = (OscarData *)gc->proto_data; |
|
| 4053 account = gaim_connection_get_account(gc); |
|
| 4054 ret = 0; |
|
| 4055 iconfile = gaim_buddy_icons_get_full_path(gaim_account_get_buddy_icon(account)); |
|
| 4056 |
|
| 4057 if (imflags & GAIM_MESSAGE_AUTO_RESP) |
|
| 4058 tmp1 = gaim_str_sub_away_formatters(message, name); |
|
| 4059 else |
|
| 4060 tmp1 = g_strdup(message); |
|
| 4061 |
|
| 4062 conn = peer_connection_find_by_type(od, name, OSCAR_CAPABILITY_DIRECTIM); |
|
| 4063 if ((conn != NULL) && (conn->ready)) |
|
| 4064 { |
|
| 4065 /* If we're directly connected, send a direct IM */ |
|
| 4066 gaim_odc_send_im(conn, tmp1, imflags); |
|
| 4067 } else { |
|
| 4068 struct buddyinfo *bi; |
|
| 4069 struct aim_sendimext_args args; |
|
| 4070 struct stat st; |
|
| 4071 gsize len; |
|
| 4072 GaimConversation *conv; |
|
| 4073 |
|
| 4074 conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, name, account); |
|
| 4075 |
|
| 4076 if (strstr(tmp1, "<IMG ")) |
|
| 4077 gaim_conversation_write(conv, "", |
|
| 4078 _("Your IM Image was not sent. " |
|
| 4079 "You must be Direct Connected to send IM Images."), |
|
| 4080 GAIM_MESSAGE_ERROR, time(NULL)); |
|
| 4081 |
|
| 4082 bi = g_hash_table_lookup(od->buddyinfo, gaim_normalize(account, name)); |
|
| 4083 if (!bi) { |
|
| 4084 bi = g_new0(struct buddyinfo, 1); |
|
| 4085 g_hash_table_insert(od->buddyinfo, g_strdup(gaim_normalize(account, name)), bi); |
|
| 4086 } |
|
| 4087 |
|
| 4088 args.flags = AIM_IMFLAGS_ACK | AIM_IMFLAGS_CUSTOMFEATURES; |
|
| 4089 if (od->icq) { |
|
| 4090 /* We have to present different "features" (whose meaning |
|
| 4091 is unclear and are merely a result of protocol inspection) |
|
| 4092 to offline ICQ buddies. Otherwise, the official |
|
| 4093 ICQ client doesn't treat those messages as being "ANSI- |
|
| 4094 encoded" (and instead, assumes them to be UTF-8). |
|
| 4095 For more details, see SF issue 1179452. |
|
| 4096 */ |
|
| 4097 GaimBuddy *buddy = gaim_find_buddy(gc->account, name); |
|
| 4098 if (buddy && GAIM_BUDDY_IS_ONLINE(buddy)) { |
|
| 4099 args.features = features_icq; |
|
| 4100 args.featureslen = sizeof(features_icq); |
|
| 4101 } else { |
|
| 4102 args.features = features_icq_offline; |
|
| 4103 args.featureslen = sizeof(features_icq_offline); |
|
| 4104 } |
|
| 4105 args.flags |= AIM_IMFLAGS_OFFLINE; |
|
| 4106 } else { |
|
| 4107 args.features = features_aim; |
|
| 4108 args.featureslen = sizeof(features_aim); |
|
| 4109 |
|
| 4110 if (imflags & GAIM_MESSAGE_AUTO_RESP) |
|
| 4111 args.flags |= AIM_IMFLAGS_AWAY; |
|
| 4112 } |
|
| 4113 |
|
| 4114 if (bi->ico_need) { |
|
| 4115 gaim_debug_info("oscar", |
|
| 4116 "Sending buddy icon request with message\n"); |
|
| 4117 args.flags |= AIM_IMFLAGS_BUDDYREQ; |
|
| 4118 bi->ico_need = FALSE; |
|
| 4119 } |
|
| 4120 |
|
| 4121 if (iconfile && !g_stat(iconfile, &st)) { |
|
| 4122 FILE *file = g_fopen(iconfile, "rb"); |
|
| 4123 if (file) { |
|
| 4124 guchar *buf = g_malloc(st.st_size); |
|
| 4125 /* TODO: Use g_file_get_contents()? */ |
|
| 4126 fread(buf, 1, st.st_size, file); |
|
| 4127 fclose(file); |
|
| 4128 |
|
| 4129 args.iconlen = st.st_size; |
|
| 4130 args.iconsum = aimutil_iconsum(buf, st.st_size); |
|
| 4131 args.iconstamp = st.st_mtime; |
|
| 4132 |
|
| 4133 if ((args.iconlen != bi->ico_me_len) || (args.iconsum != bi->ico_me_csum) || (args.iconstamp != bi->ico_me_time)) { |
|
| 4134 bi->ico_informed = FALSE; |
|
| 4135 bi->ico_sent = FALSE; |
|
| 4136 } |
|
| 4137 |
|
| 4138 if (!bi->ico_informed) { |
|
| 4139 gaim_debug_info("oscar", |
|
| 4140 "Claiming to have a buddy icon\n"); |
|
| 4141 args.flags |= AIM_IMFLAGS_HASICON; |
|
| 4142 bi->ico_me_len = args.iconlen; |
|
| 4143 bi->ico_me_csum = args.iconsum; |
|
| 4144 bi->ico_me_time = args.iconstamp; |
|
| 4145 bi->ico_informed = TRUE; |
|
| 4146 } |
|
| 4147 |
|
| 4148 g_free(buf); |
|
| 4149 } |
|
| 4150 } |
|
| 4151 g_free(iconfile); |
|
| 4152 |
|
| 4153 args.destsn = name; |
|
| 4154 |
|
| 4155 /* |
|
| 4156 * If we're IMing an SMS user or an ICQ user from an ICQ account, then strip HTML. |
|
| 4157 */ |
|
| 4158 if (aim_sn_is_sms(name)) { |
|
| 4159 /* Messaging an SMS (mobile) user */ |
|
| 4160 tmp2 = gaim_unescape_html(tmp1); |
|
| 4161 } else if (aim_sn_is_icq(gaim_account_get_username(account))) { |
|
| 4162 if (aim_sn_is_icq(name)) |
|
| 4163 /* From ICQ to ICQ */ |
|
| 4164 tmp2 = gaim_unescape_html(tmp1); |
|
| 4165 else |
|
| 4166 /* From ICQ to AIM */ |
|
| 4167 tmp2 = g_strdup(tmp1); |
|
| 4168 } else { |
|
| 4169 /* From AIM to AIM and AIM to ICQ */ |
|
| 4170 tmp2 = g_strdup(tmp1); |
|
| 4171 } |
|
| 4172 g_free(tmp1); |
|
| 4173 tmp1 = tmp2; |
|
| 4174 len = strlen(tmp1); |
|
| 4175 |
|
| 4176 gaim_plugin_oscar_convert_to_best_encoding(gc, name, tmp1, (char **)&args.msg, &args.msglen, &args.charset, &args.charsubset); |
|
| 4177 gaim_debug_info("oscar", "Sending IM, charset=0x%04hx, charsubset=0x%04hx, length=%d\n", |
|
| 4178 args.charset, args.charsubset, args.msglen); |
|
| 4179 ret = aim_im_sendch1_ext(od, &args); |
|
| 4180 g_free((char *)args.msg); |
|
| 4181 } |
|
| 4182 |
|
| 4183 g_free(tmp1); |
|
| 4184 |
|
| 4185 if (ret >= 0) |
|
| 4186 return 1; |
|
| 4187 |
|
| 4188 return ret; |
|
| 4189 } |
|
| 4190 |
|
| 4191 /* |
|
| 4192 * As of 26 June 2006, ICQ users can request AIM info from |
|
| 4193 * everyone, and can request ICQ info from ICQ users, and |
|
| 4194 * AIM users can only request AIM info. |
|
| 4195 */ |
|
| 4196 static void oscar_get_info(GaimConnection *gc, const char *name) { |
|
| 4197 OscarData *od = (OscarData *)gc->proto_data; |
|
| 4198 |
|
| 4199 if (od->icq && aim_sn_is_icq(name)) |
|
| 4200 aim_icq_getallinfo(od, name); |
|
| 4201 else |
|
| 4202 aim_locate_getinfoshort(od, name, 0x00000003); |
|
| 4203 } |
|
| 4204 |
|
| 4205 #if 0 |
|
| 4206 static void oscar_set_dir(GaimConnection *gc, const char *first, const char *middle, const char *last, |
|
| 4207 const char *maiden, const char *city, const char *state, const char *country, int web) { |
|
| 4208 /* XXX - some of these things are wrong, but i'm lazy */ |
|
| 4209 OscarData *od = (OscarData *)gc->proto_data; |
|
| 4210 aim_locate_setdirinfo(od, first, middle, last, |
|
| 4211 maiden, NULL, NULL, city, state, NULL, 0, web); |
|
| 4212 } |
|
| 4213 #endif |
|
| 4214 |
|
| 4215 static void oscar_set_idle(GaimConnection *gc, int time) { |
|
| 4216 OscarData *od = (OscarData *)gc->proto_data; |
|
| 4217 aim_srv_setidle(od, time); |
|
| 4218 } |
|
| 4219 |
|
| 4220 static |
|
| 4221 gchar *gaim_prpl_oscar_convert_to_infotext(const gchar *str, gsize *ret_len, char **encoding) |
|
| 4222 { |
|
| 4223 int charset = 0; |
|
| 4224 char *encoded = NULL; |
|
| 4225 |
|
| 4226 charset = oscar_charset_check(str); |
|
| 4227 if (charset == AIM_CHARSET_UNICODE) { |
|
| 4228 encoded = g_convert(str, strlen(str), "UCS-2BE", "UTF-8", NULL, ret_len, NULL); |
|
| 4229 *encoding = "unicode-2-0"; |
|
| 4230 } else if (charset == AIM_CHARSET_CUSTOM) { |
|
| 4231 encoded = g_convert(str, strlen(str), "ISO-8859-1", "UTF-8", NULL, ret_len, NULL); |
|
| 4232 *encoding = "iso-8859-1"; |
|
| 4233 } else { |
|
| 4234 encoded = g_strdup(str); |
|
| 4235 *ret_len = strlen(str); |
|
| 4236 *encoding = "us-ascii"; |
|
| 4237 } |
|
| 4238 |
|
| 4239 return encoded; |
|
| 4240 } |
|
| 4241 |
|
| 4242 static void |
|
| 4243 oscar_set_info(GaimConnection *gc, const char *rawinfo) |
|
| 4244 { |
|
| 4245 GaimAccount *account; |
|
| 4246 GaimStatus *status; |
|
| 4247 |
|
| 4248 account = gaim_connection_get_account(gc); |
|
| 4249 status = gaim_account_get_active_status(account); |
|
| 4250 oscar_set_info_and_status(account, TRUE, rawinfo, FALSE, status); |
|
| 4251 } |
|
| 4252 |
|
| 4253 static void |
|
| 4254 oscar_set_extendedstatus(GaimConnection *gc) |
|
| 4255 { |
|
| 4256 OscarData *od; |
|
| 4257 GaimAccount *account; |
|
| 4258 GaimStatus *status; |
|
| 4259 const gchar *status_id; |
|
| 4260 guint32 data = 0x00000000; |
|
| 4261 |
|
| 4262 od = gc->proto_data; |
|
| 4263 account = gaim_connection_get_account(gc); |
|
| 4264 status = gaim_account_get_active_status(account); |
|
| 4265 status_id = gaim_status_get_id(status); |
|
| 4266 |
|
| 4267 data |= AIM_ICQ_STATE_HIDEIP; |
|
| 4268 if (gaim_account_get_bool(account, "web_aware", OSCAR_DEFAULT_WEB_AWARE)) |
|
| 4269 data |= AIM_ICQ_STATE_WEBAWARE; |
|
| 4270 |
|
| 4271 if (!strcmp(status_id, OSCAR_STATUS_ID_AVAILABLE) || !strcmp(status_id, OSCAR_STATUS_ID_AVAILABLE)) |
|
| 4272 data |= AIM_ICQ_STATE_NORMAL; |
|
| 4273 else if (!strcmp(status_id, OSCAR_STATUS_ID_AWAY)) |
|
| 4274 data |= AIM_ICQ_STATE_AWAY; |
|
| 4275 else if (!strcmp(status_id, OSCAR_STATUS_ID_DND)) |
|
| 4276 data |= AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_DND | AIM_ICQ_STATE_BUSY; |
|
| 4277 else if (!strcmp(status_id, OSCAR_STATUS_ID_NA)) |
|
| 4278 data |= AIM_ICQ_STATE_OUT | AIM_ICQ_STATE_AWAY; |
|
| 4279 else if (!strcmp(status_id, OSCAR_STATUS_ID_OCCUPIED)) |
|
| 4280 data |= AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_BUSY; |
|
| 4281 else if (!strcmp(status_id, OSCAR_STATUS_ID_FREE4CHAT)) |
|
| 4282 data |= AIM_ICQ_STATE_CHAT; |
|
| 4283 else if (!strcmp(status_id, OSCAR_STATUS_ID_INVISIBLE)) |
|
| 4284 data |= AIM_ICQ_STATE_INVISIBLE; |
|
| 4285 else if (!strcmp(status_id, OSCAR_STATUS_ID_CUSTOM)) |
|
| 4286 data |= AIM_ICQ_STATE_OUT | AIM_ICQ_STATE_AWAY; |
|
| 4287 |
|
| 4288 aim_setextstatus(od, data); |
|
| 4289 } |
|
| 4290 |
|
| 4291 static void |
|
| 4292 oscar_set_info_and_status(GaimAccount *account, gboolean setinfo, const char *rawinfo, |
|
| 4293 gboolean setstatus, GaimStatus *status) |
|
| 4294 { |
|
| 4295 GaimConnection *gc = gaim_account_get_connection(account); |
|
| 4296 OscarData *od = gc->proto_data; |
|
| 4297 GaimPresence *presence; |
|
| 4298 GaimStatusType *status_type; |
|
| 4299 GaimStatusPrimitive primitive; |
|
| 4300 gboolean invisible; |
|
| 4301 |
|
| 4302 char *htmlinfo; |
|
| 4303 char *info_encoding = NULL; |
|
| 4304 char *info = NULL; |
|
| 4305 gsize infolen = 0; |
|
| 4306 |
|
| 4307 const char *htmlaway; |
|
| 4308 char *away_encoding = NULL; |
|
| 4309 char *away = NULL; |
|
| 4310 gsize awaylen = 0; |
|
| 4311 |
|
| 4312 status_type = gaim_status_get_type(status); |
|
| 4313 primitive = gaim_status_type_get_primitive(status_type); |
|
| 4314 presence = gaim_account_get_presence(account); |
|
| 4315 invisible = gaim_presence_is_status_primitive_active(presence, GAIM_STATUS_INVISIBLE); |
|
| 4316 |
|
| 4317 if (!setinfo) |
|
| 4318 { |
|
| 4319 /* Do nothing! */ |
|
| 4320 } |
|
| 4321 else if (od->rights.maxsiglen == 0) |
|
| 4322 { |
|
| 4323 gaim_notify_warning(gc, NULL, _("Unable to set AIM profile."), |
|
| 4324 _("You have probably requested to set your " |
|
| 4325 "profile before the login procedure completed. " |
|
| 4326 "Your profile remains unset; try setting it " |
|
| 4327 "again when you are fully connected.")); |
|
| 4328 } |
|
| 4329 else if (rawinfo != NULL) |
|
| 4330 { |
|
| 4331 htmlinfo = gaim_strdup_withhtml(rawinfo); |
|
| 4332 info = gaim_prpl_oscar_convert_to_infotext(htmlinfo, &infolen, &info_encoding); |
|
| 4333 g_free(htmlinfo); |
|
| 4334 |
|
| 4335 if (infolen > od->rights.maxsiglen) |
|
| 4336 { |
|
| 4337 gchar *errstr; |
|
| 4338 errstr = g_strdup_printf(ngettext("The maximum profile length of %d byte " |
|
| 4339 "has been exceeded. Gaim has truncated it for you.", |
|
| 4340 "The maximum profile length of %d bytes " |
|
| 4341 "has been exceeded. Gaim has truncated it for you.", |
|
| 4342 od->rights.maxsiglen), od->rights.maxsiglen); |
|
| 4343 gaim_notify_warning(gc, NULL, _("Profile too long."), errstr); |
|
| 4344 g_free(errstr); |
|
| 4345 } |
|
| 4346 } |
|
| 4347 |
|
| 4348 if (!setstatus) |
|
| 4349 { |
|
| 4350 /* Do nothing! */ |
|
| 4351 } |
|
| 4352 else if (primitive == GAIM_STATUS_AVAILABLE) |
|
| 4353 { |
|
| 4354 const char *status_html; |
|
| 4355 char *status_text = NULL; |
|
| 4356 |
|
| 4357 status_html = gaim_status_get_attr_string(status, "message"); |
|
| 4358 if (status_html != NULL) |
|
| 4359 { |
|
| 4360 status_text = gaim_markup_strip_html(status_html); |
|
| 4361 /* If the status_text is longer than 60 character then truncate it */ |
|
| 4362 if (strlen(status_text) > 60) |
|
| 4363 { |
|
| 4364 char *tmp = g_utf8_find_prev_char(status_text, &status_text[58]); |
|
| 4365 strcpy(tmp, "..."); |
|
| 4366 } |
|
| 4367 } |
|
| 4368 |
|
| 4369 aim_srv_setstatusmsg(od, status_text); |
|
| 4370 g_free(status_text); |
|
| 4371 |
|
| 4372 /* This is needed for us to un-set any previous away message. */ |
|
| 4373 away = g_strdup(""); |
|
| 4374 } |
|
| 4375 else if ((primitive == GAIM_STATUS_AWAY) || |
|
| 4376 (primitive == GAIM_STATUS_EXTENDED_AWAY)) |
|
| 4377 { |
|
| 4378 htmlaway = gaim_status_get_attr_string(status, "message"); |
|
| 4379 if ((htmlaway == NULL) || (*htmlaway == '\0')) |
|
| 4380 htmlaway = _("Away"); |
|
| 4381 away = gaim_prpl_oscar_convert_to_infotext(htmlaway, &awaylen, &away_encoding); |
|
| 4382 |
|
| 4383 if (awaylen > od->rights.maxawaymsglen) |
|
| 4384 { |
|
| 4385 gchar *errstr; |
|
| 4386 |
|
| 4387 errstr = g_strdup_printf(ngettext("The maximum away message length of %d byte " |
|
| 4388 "has been exceeded. Gaim has truncated it for you.", |
|
| 4389 "The maximum away message length of %d bytes " |
|
| 4390 "has been exceeded. Gaim has truncated it for you.", |
|
| 4391 od->rights.maxawaymsglen), od->rights.maxawaymsglen); |
|
| 4392 gaim_notify_warning(gc, NULL, _("Away message too long."), errstr); |
|
| 4393 g_free(errstr); |
|
| 4394 } |
|
| 4395 } |
|
| 4396 |
|
| 4397 if (setstatus) |
|
| 4398 oscar_set_extendedstatus(gc); |
|
| 4399 |
|
| 4400 aim_locate_setprofile(od, info_encoding, info, MIN(infolen, od->rights.maxsiglen), |
|
| 4401 away_encoding, away, MIN(awaylen, od->rights.maxawaymsglen)); |
|
| 4402 g_free(info); |
|
| 4403 g_free(away); |
|
| 4404 } |
|
| 4405 |
|
| 4406 static void |
|
| 4407 oscar_set_status_icq(GaimAccount *account, GaimStatus *status) |
|
| 4408 { |
|
| 4409 GaimConnection *gc = gaim_account_get_connection(account); |
|
| 4410 OscarData *od = NULL; |
|
| 4411 |
|
| 4412 if (gc) |
|
| 4413 od = (OscarData *)gc->proto_data; |
|
| 4414 if (!od) |
|
| 4415 return; |
|
| 4416 |
|
| 4417 if (gaim_status_type_get_primitive(gaim_status_get_type(status)) == GAIM_STATUS_INVISIBLE) |
|
| 4418 account->perm_deny = GAIM_PRIVACY_ALLOW_USERS; |
|
| 4419 else |
|
| 4420 account->perm_deny = GAIM_PRIVACY_DENY_USERS; |
|
| 4421 |
|
| 4422 if ((od->ssi.received_data) && (aim_ssi_getpermdeny(od->ssi.local) != account->perm_deny)) |
|
| 4423 aim_ssi_setpermdeny(od, account->perm_deny, 0xffffffff); |
|
| 4424 |
|
| 4425 oscar_set_extendedstatus(gc); |
|
| 4426 } |
|
| 4427 |
|
| 4428 static void |
|
| 4429 oscar_set_status(GaimAccount *account, GaimStatus *status) |
|
| 4430 { |
|
| 4431 gaim_debug_info("oscar", "Set status to %s\n", gaim_status_get_name(status)); |
|
| 4432 |
|
| 4433 if (!gaim_status_is_active(status)) |
|
| 4434 return; |
|
| 4435 |
|
| 4436 if (!gaim_account_is_connected(account)) |
|
| 4437 return; |
|
| 4438 |
|
| 4439 /* Set the AIM-style away message for both AIM and ICQ accounts */ |
|
| 4440 oscar_set_info_and_status(account, FALSE, NULL, TRUE, status); |
|
| 4441 |
|
| 4442 /* Set the ICQ status for ICQ accounts only */ |
|
| 4443 if (aim_sn_is_icq(gaim_account_get_username(account))) |
|
| 4444 oscar_set_status_icq(account, status); |
|
| 4445 } |
|
| 4446 |
|
| 4447 #ifdef CRAZY_WARN |
|
| 4448 static void |
|
| 4449 oscar_warn(GaimConnection *gc, const char *name, gboolean anonymous) { |
|
| 4450 OscarData *od = (OscarData *)gc->proto_data; |
|
| 4451 aim_im_warn(od, od->conn, name, anonymous ? AIM_WARN_ANON : 0); |
|
| 4452 } |
|
| 4453 #endif |
|
| 4454 |
|
| 4455 static void |
|
| 4456 oscar_add_buddy(GaimConnection *gc, GaimBuddy *buddy, GaimGroup *group) { |
|
| 4457 OscarData *od = (OscarData *)gc->proto_data; |
|
| 4458 |
|
| 4459 if (!aim_snvalid(buddy->name)) { |
|
| 4460 gchar *buf; |
|
| 4461 buf = g_strdup_printf(_("Could not add the buddy %s because the screen name is invalid. Screen names must either start with a letter and contain only letters, numbers and spaces, or contain only numbers."), buddy->name); |
|
| 4462 if (!gaim_conv_present_error(buddy->name, gaim_connection_get_account(gc), buf)) |
|
| 4463 gaim_notify_error(gc, NULL, _("Unable To Add"), buf); |
|
| 4464 g_free(buf); |
|
| 4465 |
|
| 4466 /* Remove from local list */ |
|
| 4467 gaim_blist_remove_buddy(buddy); |
|
| 4468 |
|
| 4469 return; |
|
| 4470 } |
|
| 4471 |
|
| 4472 if ((od->ssi.received_data) && !(aim_ssi_itemlist_finditem(od->ssi.local, group->name, buddy->name, AIM_SSI_TYPE_BUDDY))) { |
|
| 4473 gaim_debug_info("oscar", |
|
| 4474 "ssi: adding buddy %s to group %s\n", buddy->name, group->name); |
|
| 4475 aim_ssi_addbuddy(od, buddy->name, group->name, gaim_buddy_get_alias_only(buddy), NULL, NULL, 0); |
|
| 4476 } |
|
| 4477 |
|
| 4478 /* XXX - Should this be done from AIM accounts, as well? */ |
|
| 4479 if (od->icq) |
|
| 4480 aim_icq_getalias(od, buddy->name); |
|
| 4481 } |
|
| 4482 |
|
| 4483 static void oscar_remove_buddy(GaimConnection *gc, GaimBuddy *buddy, GaimGroup *group) { |
|
| 4484 OscarData *od = (OscarData *)gc->proto_data; |
|
| 4485 |
|
| 4486 if (od->ssi.received_data) { |
|
| 4487 gaim_debug_info("oscar", |
|
| 4488 "ssi: deleting buddy %s from group %s\n", buddy->name, group->name); |
|
| 4489 aim_ssi_delbuddy(od, buddy->name, group->name); |
|
| 4490 } |
|
| 4491 } |
|
| 4492 |
|
| 4493 static void oscar_move_buddy(GaimConnection *gc, const char *name, const char *old_group, const char *new_group) { |
|
| 4494 OscarData *od = (OscarData *)gc->proto_data; |
|
| 4495 if (od->ssi.received_data && strcmp(old_group, new_group)) { |
|
| 4496 gaim_debug_info("oscar", |
|
| 4497 "ssi: moving buddy %s from group %s to group %s\n", name, old_group, new_group); |
|
| 4498 aim_ssi_movebuddy(od, old_group, new_group, name); |
|
| 4499 } |
|
| 4500 } |
|
| 4501 |
|
| 4502 static void oscar_alias_buddy(GaimConnection *gc, const char *name, const char *alias) { |
|
| 4503 OscarData *od = (OscarData *)gc->proto_data; |
|
| 4504 if (od->ssi.received_data) { |
|
| 4505 char *gname = aim_ssi_itemlist_findparentname(od->ssi.local, name); |
|
| 4506 if (gname) { |
|
| 4507 gaim_debug_info("oscar", |
|
| 4508 "ssi: changing the alias for buddy %s to %s\n", name, alias ? alias : "(none)"); |
|
| 4509 aim_ssi_aliasbuddy(od, gname, name, alias); |
|
| 4510 } |
|
| 4511 } |
|
| 4512 } |
|
| 4513 |
|
| 4514 /* |
|
| 4515 * FYI, the OSCAR SSI code removes empty groups automatically. |
|
| 4516 */ |
|
| 4517 static void oscar_rename_group(GaimConnection *gc, const char *old_name, GaimGroup *group, GList *moved_buddies) { |
|
| 4518 OscarData *od = (OscarData *)gc->proto_data; |
|
| 4519 |
|
| 4520 if (od->ssi.received_data) { |
|
| 4521 if (aim_ssi_itemlist_finditem(od->ssi.local, group->name, NULL, AIM_SSI_TYPE_GROUP)) { |
|
| 4522 GList *cur, *groups = NULL; |
|
| 4523 GaimAccount *account = gaim_connection_get_account(gc); |
|
| 4524 |
|
| 4525 /* Make a list of what the groups each buddy is in */ |
|
| 4526 for (cur = moved_buddies; cur != NULL; cur = cur->next) { |
|
| 4527 GaimBlistNode *node = cur->data; |
|
| 4528 /* node is GaimBuddy, parent is a GaimContact. |
|
| 4529 * We must go two levels up to get the Group */ |
|
| 4530 groups = g_list_append(groups, |
|
| 4531 node->parent->parent); |
|
| 4532 } |
|
| 4533 |
|
| 4534 gaim_account_remove_buddies(account, moved_buddies, groups); |
|
| 4535 gaim_account_add_buddies(account, moved_buddies); |
|
| 4536 g_list_free(groups); |
|
| 4537 gaim_debug_info("oscar", |
|
| 4538 "ssi: moved all buddies from group %s to %s\n", old_name, group->name); |
|
| 4539 } else { |
|
| 4540 aim_ssi_rename_group(od, old_name, group->name); |
|
| 4541 gaim_debug_info("oscar", |
|
| 4542 "ssi: renamed group %s to %s\n", old_name, group->name); |
|
| 4543 } |
|
| 4544 } |
|
| 4545 } |
|
| 4546 |
|
| 4547 static gboolean gaim_ssi_rerequestdata(gpointer data) { |
|
| 4548 OscarData *od = data; |
|
| 4549 |
|
| 4550 aim_ssi_reqdata(od); |
|
| 4551 |
|
| 4552 return TRUE; |
|
| 4553 } |
|
| 4554 |
|
| 4555 static int gaim_ssi_parseerr(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 4556 GaimConnection *gc = od->gc; |
|
| 4557 va_list ap; |
|
| 4558 guint16 reason; |
|
| 4559 |
|
| 4560 va_start(ap, fr); |
|
| 4561 reason = (guint16)va_arg(ap, unsigned int); |
|
| 4562 va_end(ap); |
|
| 4563 |
|
| 4564 gaim_debug_error("oscar", "ssi: SNAC error %hu\n", reason); |
|
| 4565 |
|
| 4566 if (reason == 0x0005) { |
|
| 4567 gaim_notify_error(gc, NULL, _("Unable To Retrieve Buddy List"), |
|
| 4568 _("Gaim was temporarily unable to retrieve your buddy list from the AIM servers. Your buddy list is not lost, and will probably become available in a few hours.")); |
|
| 4569 if (od->getblisttimer > 0) |
|
| 4570 gaim_timeout_remove(od->getblisttimer); |
|
| 4571 od->getblisttimer = gaim_timeout_add(30000, gaim_ssi_rerequestdata, od); |
|
| 4572 } |
|
| 4573 |
|
| 4574 oscar_set_extendedstatus(gc); |
|
| 4575 |
|
| 4576 /* Activate SSI */ |
|
| 4577 /* Sending the enable causes other people to be able to see you, and you to see them */ |
|
| 4578 /* Make sure your privacy setting/invisibility is set how you want it before this! */ |
|
| 4579 gaim_debug_info("oscar", "ssi: activating server-stored buddy list\n"); |
|
| 4580 aim_ssi_enable(od); |
|
| 4581 |
|
| 4582 return 1; |
|
| 4583 } |
|
| 4584 |
|
| 4585 static int gaim_ssi_parserights(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 4586 int i; |
|
| 4587 va_list ap; |
|
| 4588 int numtypes; |
|
| 4589 guint16 *maxitems; |
|
| 4590 |
|
| 4591 va_start(ap, fr); |
|
| 4592 numtypes = va_arg(ap, int); |
|
| 4593 maxitems = va_arg(ap, guint16 *); |
|
| 4594 va_end(ap); |
|
| 4595 |
|
| 4596 gaim_debug_misc("oscar", "ssi rights:"); |
|
| 4597 |
|
| 4598 for (i=0; i<numtypes; i++) |
|
| 4599 gaim_debug_misc(NULL, " max type 0x%04x=%hd,", |
|
| 4600 i, maxitems[i]); |
|
| 4601 |
|
| 4602 gaim_debug_misc(NULL, "\n"); |
|
| 4603 |
|
| 4604 if (numtypes >= 0) |
|
| 4605 od->rights.maxbuddies = maxitems[0]; |
|
| 4606 if (numtypes >= 1) |
|
| 4607 od->rights.maxgroups = maxitems[1]; |
|
| 4608 if (numtypes >= 2) |
|
| 4609 od->rights.maxpermits = maxitems[2]; |
|
| 4610 if (numtypes >= 3) |
|
| 4611 od->rights.maxdenies = maxitems[3]; |
|
| 4612 |
|
| 4613 return 1; |
|
| 4614 } |
|
| 4615 |
|
| 4616 static int gaim_ssi_parselist(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) |
|
| 4617 { |
|
| 4618 GaimConnection *gc; |
|
| 4619 GaimAccount *account; |
|
| 4620 GaimGroup *g; |
|
| 4621 GaimBuddy *b; |
|
| 4622 struct aim_ssi_item *curitem; |
|
| 4623 guint32 tmp; |
|
| 4624 va_list ap; |
|
| 4625 guint16 fmtver, numitems; |
|
| 4626 guint32 timestamp; |
|
| 4627 |
|
| 4628 gc = od->gc; |
|
| 4629 od = gc->proto_data; |
|
| 4630 account = gaim_connection_get_account(gc); |
|
| 4631 |
|
| 4632 va_start(ap, fr); |
|
| 4633 fmtver = (guint16)va_arg(ap, int); |
|
| 4634 numitems = (guint16)va_arg(ap, int); |
|
| 4635 timestamp = va_arg(ap, guint32); |
|
| 4636 va_end(ap); |
|
| 4637 |
|
| 4638 /* Don't attempt to re-request our buddy list later */ |
|
| 4639 if (od->getblisttimer != 0) |
|
| 4640 gaim_timeout_remove(od->getblisttimer); |
|
| 4641 od->getblisttimer = 0; |
|
| 4642 |
|
| 4643 gaim_debug_info("oscar", |
|
| 4644 "ssi: syncing local list and server list\n"); |
|
| 4645 |
|
| 4646 if ((timestamp == 0) || (numitems == 0)) { |
|
| 4647 gaim_debug_info("oscar", "Got AIM SSI with a 0 timestamp or 0 numitems--not syncing. This probably means your buddy list is empty.", NULL); |
|
| 4648 return 1; |
|
| 4649 } |
|
| 4650 |
|
| 4651 /* Clean the buddy list */ |
|
| 4652 aim_ssi_cleanlist(od); |
|
| 4653 |
|
| 4654 { /* If not in server list then prune from local list */ |
|
| 4655 GaimBlistNode *gnode, *cnode, *bnode; |
|
| 4656 GaimBuddyList *blist; |
|
| 4657 GSList *cur, *next; |
|
| 4658 |
|
| 4659 /* Buddies */ |
|
| 4660 cur = NULL; |
|
| 4661 if ((blist = gaim_get_blist()) != NULL) { |
|
| 4662 for (gnode = blist->root; gnode; gnode = gnode->next) { |
|
| 4663 if(!GAIM_BLIST_NODE_IS_GROUP(gnode)) |
|
| 4664 continue; |
|
| 4665 g = (GaimGroup *)gnode; |
|
| 4666 for (cnode = gnode->child; cnode; cnode = cnode->next) { |
|
| 4667 if(!GAIM_BLIST_NODE_IS_CONTACT(cnode)) |
|
| 4668 continue; |
|
| 4669 for (bnode = cnode->child; bnode; bnode = bnode->next) { |
|
| 4670 if(!GAIM_BLIST_NODE_IS_BUDDY(bnode)) |
|
| 4671 continue; |
|
| 4672 b = (GaimBuddy *)bnode; |
|
| 4673 if (b->account == gc->account) { |
|
| 4674 if (aim_ssi_itemlist_exists(od->ssi.local, b->name)) { |
|
| 4675 /* If the buddy is an ICQ user then load his nickname */ |
|
| 4676 const char *servernick = gaim_blist_node_get_string((GaimBlistNode*)b, "servernick"); |
|
| 4677 char *alias; |
|
| 4678 if (servernick) |
|
| 4679 serv_got_alias(gc, b->name, servernick); |
|
| 4680 |
|
| 4681 /* Store local alias on server */ |
|
| 4682 alias = aim_ssi_getalias(od->ssi.local, g->name, b->name); |
|
| 4683 if (!alias && b->alias && strlen(b->alias)) |
|
| 4684 aim_ssi_aliasbuddy(od, g->name, b->name, b->alias); |
|
| 4685 g_free(alias); |
|
| 4686 } else { |
|
| 4687 gaim_debug_info("oscar", |
|
| 4688 "ssi: removing buddy %s from local list\n", b->name); |
|
| 4689 /* We can't actually remove now because it will screw up our looping */ |
|
| 4690 cur = g_slist_prepend(cur, b); |
|
| 4691 } |
|
| 4692 } |
|
| 4693 } |
|
| 4694 } |
|
| 4695 } |
|
| 4696 } |
|
| 4697 |
|
| 4698 while (cur != NULL) { |
|
| 4699 b = cur->data; |
|
| 4700 cur = g_slist_remove(cur, b); |
|
| 4701 gaim_blist_remove_buddy(b); |
|
| 4702 } |
|
| 4703 |
|
| 4704 /* Permit list */ |
|
| 4705 if (gc->account->permit) { |
|
| 4706 next = gc->account->permit; |
|
| 4707 while (next != NULL) { |
|
| 4708 cur = next; |
|
| 4709 next = next->next; |
|
| 4710 if (!aim_ssi_itemlist_finditem(od->ssi.local, NULL, cur->data, AIM_SSI_TYPE_PERMIT)) { |
|
| 4711 gaim_debug_info("oscar", |
|
| 4712 "ssi: removing permit %s from local list\n", (const char *)cur->data); |
|
| 4713 gaim_privacy_permit_remove(account, cur->data, TRUE); |
|
| 4714 } |
|
| 4715 } |
|
| 4716 } |
|
| 4717 |
|
| 4718 /* Deny list */ |
|
| 4719 if (gc->account->deny) { |
|
| 4720 next = gc->account->deny; |
|
| 4721 while (next != NULL) { |
|
| 4722 cur = next; |
|
| 4723 next = next->next; |
|
| 4724 if (!aim_ssi_itemlist_finditem(od->ssi.local, NULL, cur->data, AIM_SSI_TYPE_DENY)) { |
|
| 4725 gaim_debug_info("oscar", |
|
| 4726 "ssi: removing deny %s from local list\n", (const char *)cur->data); |
|
| 4727 gaim_privacy_deny_remove(account, cur->data, TRUE); |
|
| 4728 } |
|
| 4729 } |
|
| 4730 } |
|
| 4731 /* Presence settings (idle time visibility) */ |
|
| 4732 if ((tmp = aim_ssi_getpresence(od->ssi.local)) != 0xFFFFFFFF) |
|
| 4733 if (!(tmp & 0x400)) |
|
| 4734 aim_ssi_setpresence(od, tmp | 0x400); |
|
| 4735 } /* end pruning buddies from local list */ |
|
| 4736 |
|
| 4737 /* Add from server list to local list */ |
|
| 4738 for (curitem=od->ssi.local; curitem; curitem=curitem->next) { |
|
| 4739 if ((curitem->name == NULL) || (g_utf8_validate(curitem->name, -1, NULL))) |
|
| 4740 switch (curitem->type) { |
|
| 4741 case 0x0000: { /* Buddy */ |
|
| 4742 if (curitem->name) { |
|
| 4743 char *gname = aim_ssi_itemlist_findparentname(od->ssi.local, curitem->name); |
|
| 4744 char *gname_utf8 = gname ? oscar_utf8_try_convert(gc->account, gname) : NULL; |
|
| 4745 char *alias = aim_ssi_getalias(od->ssi.local, gname, curitem->name); |
|
| 4746 char *alias_utf8; |
|
| 4747 |
|
| 4748 if (alias != NULL) |
|
| 4749 { |
|
| 4750 if (g_utf8_validate(alias, -1, NULL)) |
|
| 4751 alias_utf8 = g_strdup(alias); |
|
| 4752 else |
|
| 4753 alias_utf8 = oscar_utf8_try_convert(account, alias); |
|
| 4754 } |
|
| 4755 else |
|
| 4756 alias_utf8 = NULL; |
|
| 4757 |
|
| 4758 b = gaim_find_buddy(gc->account, curitem->name); |
|
| 4759 /* Should gname be freed here? -- elb */ |
|
| 4760 /* Not with the current code, but that might be cleaner -- med */ |
|
| 4761 g_free(alias); |
|
| 4762 if (b) { |
|
| 4763 /* Get server stored alias */ |
|
| 4764 if (alias_utf8) { |
|
| 4765 g_free(b->alias); |
|
| 4766 b->alias = g_strdup(alias_utf8); |
|
| 4767 } |
|
| 4768 } else { |
|
| 4769 b = gaim_buddy_new(gc->account, curitem->name, alias_utf8); |
|
| 4770 |
|
| 4771 if (!(g = gaim_find_group(gname_utf8 ? gname_utf8 : _("Orphans")))) { |
|
| 4772 g = gaim_group_new(gname_utf8 ? gname_utf8 : _("Orphans")); |
|
| 4773 gaim_blist_add_group(g, NULL); |
|
| 4774 } |
|
| 4775 |
|
| 4776 gaim_debug_info("oscar", |
|
| 4777 "ssi: adding buddy %s to group %s to local list\n", curitem->name, gname_utf8 ? gname_utf8 : _("Orphans")); |
|
| 4778 gaim_blist_add_buddy(b, NULL, g, NULL); |
|
| 4779 } |
|
| 4780 if (!aim_sncmp(curitem->name, account->username)) { |
|
| 4781 char *comment = aim_ssi_getcomment(od->ssi.local, gname, curitem->name); |
|
| 4782 gaim_check_comment(od, comment); |
|
| 4783 g_free(comment); |
|
| 4784 } |
|
| 4785 g_free(gname_utf8); |
|
| 4786 g_free(alias_utf8); |
|
| 4787 } |
|
| 4788 } break; |
|
| 4789 |
|
| 4790 case 0x0001: { /* Group */ |
|
| 4791 /* Shouldn't add empty groups */ |
|
| 4792 } break; |
|
| 4793 |
|
| 4794 case 0x0002: { /* Permit buddy */ |
|
| 4795 if (curitem->name) { |
|
| 4796 /* if (!find_permdeny_by_name(gc->permit, curitem->name)) { AAA */ |
|
| 4797 GSList *list; |
|
| 4798 for (list=account->permit; (list && aim_sncmp(curitem->name, list->data)); list=list->next); |
|
| 4799 if (!list) { |
|
| 4800 gaim_debug_info("oscar", |
|
| 4801 "ssi: adding permit buddy %s to local list\n", curitem->name); |
|
| 4802 gaim_privacy_permit_add(account, curitem->name, TRUE); |
|
| 4803 } |
|
| 4804 } |
|
| 4805 } break; |
|
| 4806 |
|
| 4807 case 0x0003: { /* Deny buddy */ |
|
| 4808 if (curitem->name) { |
|
| 4809 GSList *list; |
|
| 4810 for (list=account->deny; (list && aim_sncmp(curitem->name, list->data)); list=list->next); |
|
| 4811 if (!list) { |
|
| 4812 gaim_debug_info("oscar", |
|
| 4813 "ssi: adding deny buddy %s to local list\n", curitem->name); |
|
| 4814 gaim_privacy_deny_add(account, curitem->name, TRUE); |
|
| 4815 } |
|
| 4816 } |
|
| 4817 } break; |
|
| 4818 |
|
| 4819 case 0x0004: { /* Permit/deny setting */ |
|
| 4820 if (curitem->data) { |
|
| 4821 guint8 permdeny; |
|
| 4822 if ((permdeny = aim_ssi_getpermdeny(od->ssi.local)) && (permdeny != account->perm_deny)) { |
|
| 4823 gaim_debug_info("oscar", |
|
| 4824 "ssi: changing permdeny from %d to %hhu\n", account->perm_deny, permdeny); |
|
| 4825 account->perm_deny = permdeny; |
|
| 4826 if (od->icq && account->perm_deny == GAIM_PRIVACY_ALLOW_USERS) { |
|
| 4827 gaim_presence_set_status_active(account->presence, OSCAR_STATUS_ID_INVISIBLE, TRUE); |
|
| 4828 } |
|
| 4829 } |
|
| 4830 } |
|
| 4831 } break; |
|
| 4832 |
|
| 4833 case 0x0005: { /* Presence setting */ |
|
| 4834 /* We don't want to change Gaim's setting because it applies to all accounts */ |
|
| 4835 } break; |
|
| 4836 } /* End of switch on curitem->type */ |
|
| 4837 } /* End of for loop */ |
|
| 4838 |
|
| 4839 oscar_set_extendedstatus(gc); |
|
| 4840 |
|
| 4841 /* Activate SSI */ |
|
| 4842 /* Sending the enable causes other people to be able to see you, and you to see them */ |
|
| 4843 /* Make sure your privacy setting/invisibility is set how you want it before this! */ |
|
| 4844 gaim_debug_info("oscar", |
|
| 4845 "ssi: activating server-stored buddy list\n"); |
|
| 4846 aim_ssi_enable(od); |
|
| 4847 |
|
| 4848 return 1; |
|
| 4849 } |
|
| 4850 |
|
| 4851 static int gaim_ssi_parseack(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 4852 GaimConnection *gc = od->gc; |
|
| 4853 va_list ap; |
|
| 4854 struct aim_ssi_tmp *retval; |
|
| 4855 |
|
| 4856 va_start(ap, fr); |
|
| 4857 retval = va_arg(ap, struct aim_ssi_tmp *); |
|
| 4858 va_end(ap); |
|
| 4859 |
|
| 4860 while (retval) { |
|
| 4861 gaim_debug_misc("oscar", |
|
| 4862 "ssi: status is 0x%04hx for a 0x%04hx action with name %s\n", retval->ack, retval->action, retval->item ? (retval->item->name ? retval->item->name : "no name") : "no item"); |
|
| 4863 |
|
| 4864 if (retval->ack != 0xffff) |
|
| 4865 switch (retval->ack) { |
|
| 4866 case 0x0000: { /* added successfully */ |
|
| 4867 } break; |
|
| 4868 |
|
| 4869 case 0x000c: { /* you are over the limit, the cheat is to the limit, come on fhqwhgads */ |
|
| 4870 gchar *buf; |
|
| 4871 buf = g_strdup_printf(_("Could not add the buddy %s because you have too many buddies in your buddy list. Please remove one and try again."), (retval->name ? retval->name : _("(no name)"))); |
|
| 4872 if ((retval->name != NULL) && !gaim_conv_present_error(retval->name, gaim_connection_get_account(gc), buf)) |
|
| 4873 gaim_notify_error(gc, NULL, _("Unable To Add"), buf); |
|
| 4874 g_free(buf); |
|
| 4875 } |
|
| 4876 |
|
| 4877 case 0x000e: { /* buddy requires authorization */ |
|
| 4878 if ((retval->action == SNAC_SUBTYPE_FEEDBAG_ADD) && (retval->name)) |
|
| 4879 gaim_auth_sendrequest(gc, retval->name); |
|
| 4880 } break; |
|
| 4881 |
|
| 4882 default: { /* La la la */ |
|
| 4883 gchar *buf; |
|
| 4884 gaim_debug_error("oscar", "ssi: Action 0x%04hx was unsuccessful with error 0x%04hx\n", retval->action, retval->ack); |
|
| 4885 buf = g_strdup_printf(_("Could not add the buddy %s for an unknown reason. The most common reason for this is that you have the maximum number of allowed buddies in your buddy list."), (retval->name ? retval->name : _("(no name)"))); |
|
| 4886 if ((retval->name != NULL) && !gaim_conv_present_error(retval->name, gaim_connection_get_account(gc), buf)) |
|
| 4887 gaim_notify_error(gc, NULL, _("Unable To Add"), buf); |
|
| 4888 g_free(buf); |
|
| 4889 } break; |
|
| 4890 } |
|
| 4891 |
|
| 4892 retval = retval->next; |
|
| 4893 } |
|
| 4894 |
|
| 4895 return 1; |
|
| 4896 } |
|
| 4897 |
|
| 4898 static int gaim_ssi_parseadd(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 4899 GaimConnection *gc = od->gc; |
|
| 4900 char *gname, *gname_utf8, *alias, *alias_utf8; |
|
| 4901 GaimBuddy *b; |
|
| 4902 GaimGroup *g; |
|
| 4903 va_list ap; |
|
| 4904 guint16 type; |
|
| 4905 const char *name; |
|
| 4906 |
|
| 4907 va_start(ap, fr); |
|
| 4908 type = (guint16)va_arg(ap, int); |
|
| 4909 name = va_arg(ap, char *); |
|
| 4910 va_end(ap); |
|
| 4911 |
|
| 4912 if ((type != 0x0000) || (name == NULL)) |
|
| 4913 return 1; |
|
| 4914 |
|
| 4915 gname = aim_ssi_itemlist_findparentname(od->ssi.local, name); |
|
| 4916 gname_utf8 = gname ? oscar_utf8_try_convert(gc->account, gname) : NULL; |
|
| 4917 |
|
| 4918 alias = aim_ssi_getalias(od->ssi.local, gname, name); |
|
| 4919 if (alias != NULL) |
|
| 4920 { |
|
| 4921 if (g_utf8_validate(alias, -1, NULL)) |
|
| 4922 alias_utf8 = g_strdup(alias); |
|
| 4923 else |
|
| 4924 alias_utf8 = oscar_utf8_try_convert(gaim_connection_get_account(gc), alias); |
|
| 4925 } |
|
| 4926 else |
|
| 4927 alias_utf8 = NULL; |
|
| 4928 |
|
| 4929 b = gaim_find_buddy(gc->account, name); |
|
| 4930 g_free(alias); |
|
| 4931 |
|
| 4932 if (b) { |
|
| 4933 /* Get server stored alias */ |
|
| 4934 if (alias_utf8) { |
|
| 4935 g_free(b->alias); |
|
| 4936 b->alias = g_strdup(alias_utf8); |
|
| 4937 } |
|
| 4938 } else { |
|
| 4939 b = gaim_buddy_new(gc->account, name, alias_utf8); |
|
| 4940 |
|
| 4941 if (!(g = gaim_find_group(gname_utf8 ? gname_utf8 : _("Orphans")))) { |
|
| 4942 g = gaim_group_new(gname_utf8 ? gname_utf8 : _("Orphans")); |
|
| 4943 gaim_blist_add_group(g, NULL); |
|
| 4944 } |
|
| 4945 |
|
| 4946 gaim_debug_info("oscar", |
|
| 4947 "ssi: adding buddy %s to group %s to local list\n", name, gname_utf8 ? gname_utf8 : _("Orphans")); |
|
| 4948 gaim_blist_add_buddy(b, NULL, g, NULL); |
|
| 4949 } |
|
| 4950 g_free(gname_utf8); |
|
| 4951 g_free(alias_utf8); |
|
| 4952 |
|
| 4953 return 1; |
|
| 4954 } |
|
| 4955 |
|
| 4956 static int gaim_ssi_authgiven(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 4957 GaimConnection *gc = od->gc; |
|
| 4958 va_list ap; |
|
| 4959 char *sn, *msg; |
|
| 4960 gchar *dialog_msg, *nombre; |
|
| 4961 struct name_data *data; |
|
| 4962 GaimBuddy *buddy; |
|
| 4963 |
|
| 4964 va_start(ap, fr); |
|
| 4965 sn = va_arg(ap, char *); |
|
| 4966 msg = va_arg(ap, char *); |
|
| 4967 va_end(ap); |
|
| 4968 |
|
| 4969 gaim_debug_info("oscar", |
|
| 4970 "ssi: %s has given you permission to add him to your buddy list\n", sn); |
|
| 4971 |
|
| 4972 buddy = gaim_find_buddy(gc->account, sn); |
|
| 4973 if (buddy && (gaim_buddy_get_alias_only(buddy))) |
|
| 4974 nombre = g_strdup_printf("%s (%s)", sn, gaim_buddy_get_alias_only(buddy)); |
|
| 4975 else |
|
| 4976 nombre = g_strdup(sn); |
|
| 4977 |
|
| 4978 dialog_msg = g_strdup_printf(_("The user %s has given you permission to add you to their buddy list. Do you want to add them?"), nombre); |
|
| 4979 data = g_new(struct name_data, 1); |
|
| 4980 data->gc = gc; |
|
| 4981 data->name = g_strdup(sn); |
|
| 4982 data->nick = NULL; |
|
| 4983 |
|
| 4984 gaim_request_yes_no(gc, NULL, _("Authorization Given"), dialog_msg, |
|
| 4985 GAIM_DEFAULT_ACTION_NONE, data, |
|
| 4986 G_CALLBACK(gaim_icq_buddyadd), |
|
| 4987 G_CALLBACK(oscar_free_name_data)); |
|
| 4988 |
|
| 4989 g_free(dialog_msg); |
|
| 4990 g_free(nombre); |
|
| 4991 |
|
| 4992 return 1; |
|
| 4993 } |
|
| 4994 |
|
| 4995 static int gaim_ssi_authrequest(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 4996 GaimConnection *gc = od->gc; |
|
| 4997 va_list ap; |
|
| 4998 char *sn; |
|
| 4999 char *msg; |
|
| 5000 GaimAccount *account = gaim_connection_get_account(gc); |
|
| 5001 gchar *nombre; |
|
| 5002 gchar *reason = NULL; |
|
| 5003 gchar *dialog_msg; |
|
| 5004 struct name_data *data; |
|
| 5005 GaimBuddy *buddy; |
|
| 5006 |
|
| 5007 va_start(ap, fr); |
|
| 5008 sn = va_arg(ap, char *); |
|
| 5009 msg = va_arg(ap, char *); |
|
| 5010 va_end(ap); |
|
| 5011 |
|
| 5012 gaim_debug_info("oscar", |
|
| 5013 "ssi: received authorization request from %s\n", sn); |
|
| 5014 |
|
| 5015 buddy = gaim_find_buddy(account, sn); |
|
| 5016 if (buddy && (gaim_buddy_get_alias_only(buddy))) |
|
| 5017 nombre = g_strdup_printf("%s (%s)", sn, gaim_buddy_get_alias_only(buddy)); |
|
| 5018 else |
|
| 5019 nombre = g_strdup(sn); |
|
| 5020 |
|
| 5021 if (msg != NULL) |
|
| 5022 reason = gaim_plugin_oscar_decode_im_part(account, sn, AIM_CHARSET_CUSTOM, 0x0000, msg, strlen(msg)); |
|
| 5023 |
|
| 5024 if (reason == NULL) |
|
| 5025 reason = g_strdup(_("No reason given.")); |
|
| 5026 |
|
| 5027 dialog_msg = g_strdup_printf( |
|
| 5028 _("The user %s wants to add %s to their buddy list for the following reason:\n%s"), |
|
| 5029 nombre, gaim_account_get_username(account), reason); |
|
| 5030 g_free(reason); |
|
| 5031 |
|
| 5032 data = g_new(struct name_data, 1); |
|
| 5033 data->gc = gc; |
|
| 5034 data->name = g_strdup(sn); |
|
| 5035 data->nick = NULL; |
|
| 5036 |
|
| 5037 gaim_request_action(gc, NULL, _("Authorization Request"), dialog_msg, |
|
| 5038 GAIM_DEFAULT_ACTION_NONE, data, 2, |
|
| 5039 _("_Authorize"), G_CALLBACK(gaim_auth_grant), |
|
| 5040 _("_Deny"), G_CALLBACK(gaim_auth_dontgrant_msgprompt)); |
|
| 5041 |
|
| 5042 g_free(dialog_msg); |
|
| 5043 g_free(nombre); |
|
| 5044 |
|
| 5045 return 1; |
|
| 5046 } |
|
| 5047 |
|
| 5048 static int gaim_ssi_authreply(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 5049 GaimConnection *gc = od->gc; |
|
| 5050 va_list ap; |
|
| 5051 char *sn, *msg; |
|
| 5052 gchar *dialog_msg, *nombre; |
|
| 5053 guint8 reply; |
|
| 5054 GaimBuddy *buddy; |
|
| 5055 |
|
| 5056 va_start(ap, fr); |
|
| 5057 sn = va_arg(ap, char *); |
|
| 5058 reply = (guint8)va_arg(ap, int); |
|
| 5059 msg = va_arg(ap, char *); |
|
| 5060 va_end(ap); |
|
| 5061 |
|
| 5062 gaim_debug_info("oscar", |
|
| 5063 "ssi: received authorization reply from %s. Reply is 0x%04hhx\n", sn, reply); |
|
| 5064 |
|
| 5065 buddy = gaim_find_buddy(gc->account, sn); |
|
| 5066 if (buddy && (gaim_buddy_get_alias_only(buddy))) |
|
| 5067 nombre = g_strdup_printf("%s (%s)", sn, gaim_buddy_get_alias_only(buddy)); |
|
| 5068 else |
|
| 5069 nombre = g_strdup(sn); |
|
| 5070 |
|
| 5071 if (reply) { |
|
| 5072 /* Granted */ |
|
| 5073 dialog_msg = g_strdup_printf(_("The user %s has granted your request to add them to your buddy list."), nombre); |
|
| 5074 gaim_notify_info(gc, NULL, _("Authorization Granted"), dialog_msg); |
|
| 5075 } else { |
|
| 5076 /* Denied */ |
|
| 5077 dialog_msg = g_strdup_printf(_("The user %s has denied your request to add them to your buddy list for the following reason:\n%s"), nombre, msg ? msg : _("No reason given.")); |
|
| 5078 gaim_notify_info(gc, NULL, _("Authorization Denied"), dialog_msg); |
|
| 5079 } |
|
| 5080 g_free(dialog_msg); |
|
| 5081 g_free(nombre); |
|
| 5082 |
|
| 5083 return 1; |
|
| 5084 } |
|
| 5085 |
|
| 5086 static int gaim_ssi_gotadded(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 5087 GaimConnection *gc = od->gc; |
|
| 5088 va_list ap; |
|
| 5089 char *sn; |
|
| 5090 GaimBuddy *buddy; |
|
| 5091 |
|
| 5092 va_start(ap, fr); |
|
| 5093 sn = va_arg(ap, char *); |
|
| 5094 va_end(ap); |
|
| 5095 |
|
| 5096 buddy = gaim_find_buddy(gc->account, sn); |
|
| 5097 gaim_debug_info("oscar", "ssi: %s added you to their buddy list\n", sn); |
|
| 5098 gaim_account_notify_added(gc->account, sn, NULL, (buddy ? gaim_buddy_get_alias_only(buddy) : NULL), NULL); |
|
| 5099 |
|
| 5100 return 1; |
|
| 5101 } |
|
| 5102 |
|
| 5103 static GList *oscar_chat_info(GaimConnection *gc) { |
|
| 5104 GList *m = NULL; |
|
| 5105 struct proto_chat_entry *pce; |
|
| 5106 |
|
| 5107 pce = g_new0(struct proto_chat_entry, 1); |
|
| 5108 pce->label = _("_Room:"); |
|
| 5109 pce->identifier = "room"; |
|
| 5110 pce->required = TRUE; |
|
| 5111 m = g_list_append(m, pce); |
|
| 5112 |
|
| 5113 pce = g_new0(struct proto_chat_entry, 1); |
|
| 5114 pce->label = _("_Exchange:"); |
|
| 5115 pce->identifier = "exchange"; |
|
| 5116 pce->required = TRUE; |
|
| 5117 pce->is_int = TRUE; |
|
| 5118 pce->min = 4; |
|
| 5119 pce->max = 20; |
|
| 5120 m = g_list_append(m, pce); |
|
| 5121 |
|
| 5122 return m; |
|
| 5123 } |
|
| 5124 |
|
| 5125 static GHashTable *oscar_chat_info_defaults(GaimConnection *gc, const char *chat_name) |
|
| 5126 { |
|
| 5127 GHashTable *defaults; |
|
| 5128 |
|
| 5129 defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); |
|
| 5130 |
|
| 5131 if (chat_name != NULL) |
|
| 5132 g_hash_table_insert(defaults, "room", g_strdup(chat_name)); |
|
| 5133 |
|
| 5134 return defaults; |
|
| 5135 } |
|
| 5136 |
|
| 5137 static char * |
|
| 5138 oscar_get_chat_name(GHashTable *data) |
|
| 5139 { |
|
| 5140 return g_strdup(g_hash_table_lookup(data, "room")); |
|
| 5141 } |
|
| 5142 |
|
| 5143 static void |
|
| 5144 oscar_join_chat(GaimConnection *gc, GHashTable *data) |
|
| 5145 { |
|
| 5146 OscarData *od = (OscarData *)gc->proto_data; |
|
| 5147 FlapConnection *conn; |
|
| 5148 char *name, *exchange; |
|
| 5149 |
|
| 5150 name = g_hash_table_lookup(data, "room"); |
|
| 5151 exchange = g_hash_table_lookup(data, "exchange"); |
|
| 5152 |
|
| 5153 if ((name == NULL) || (*name == '\0')) { |
|
| 5154 gaim_notify_error(gc, NULL, _("Invalid chat name specified."), NULL); |
|
| 5155 return; |
|
| 5156 } |
|
| 5157 |
|
| 5158 gaim_debug_info("oscar", "Attempting to join chat room %s.\n", name); |
|
| 5159 |
|
| 5160 if ((conn = flap_connection_getbytype(od, SNAC_FAMILY_CHATNAV))) |
|
| 5161 { |
|
| 5162 gaim_debug_info("oscar", "chatnav exists, creating room\n"); |
|
| 5163 aim_chatnav_createroom(od, conn, name, atoi(exchange)); |
|
| 5164 } else { |
|
| 5165 /* this gets tricky */ |
|
| 5166 struct create_room *cr = g_new0(struct create_room, 1); |
|
| 5167 gaim_debug_info("oscar", "chatnav does not exist, opening chatnav\n"); |
|
| 5168 cr->exchange = atoi(exchange); |
|
| 5169 cr->name = g_strdup(name); |
|
| 5170 od->create_rooms = g_slist_append(od->create_rooms, cr); |
|
| 5171 aim_reqservice(od, SNAC_FAMILY_CHATNAV); |
|
| 5172 } |
|
| 5173 } |
|
| 5174 |
|
| 5175 static void |
|
| 5176 oscar_chat_invite(GaimConnection *gc, int id, const char *message, const char *name) |
|
| 5177 { |
|
| 5178 OscarData *od = (OscarData *)gc->proto_data; |
|
| 5179 struct chat_connection *ccon = find_oscar_chat(gc, id); |
|
| 5180 |
|
| 5181 if (ccon == NULL) |
|
| 5182 return; |
|
| 5183 |
|
| 5184 aim_im_sendch2_chatinvite(od, name, message ? message : "", |
|
| 5185 ccon->exchange, ccon->name, 0x0); |
|
| 5186 } |
|
| 5187 |
|
| 5188 static void |
|
| 5189 oscar_chat_leave(GaimConnection *gc, int id) |
|
| 5190 { |
|
| 5191 GaimConversation *conv; |
|
| 5192 struct chat_connection *cc; |
|
| 5193 |
|
| 5194 conv = gaim_find_chat(gc, id); |
|
| 5195 |
|
| 5196 g_return_if_fail(conv != NULL); |
|
| 5197 |
|
| 5198 gaim_debug_info("oscar", "Leaving chat room %s\n", conv->name); |
|
| 5199 |
|
| 5200 cc = find_oscar_chat(gc, gaim_conv_chat_get_id(GAIM_CONV_CHAT(conv))); |
|
| 5201 oscar_chat_kill(gc, cc); |
|
| 5202 } |
|
| 5203 |
|
| 5204 static int oscar_send_chat(GaimConnection *gc, int id, const char *message, GaimMessageFlags flags) { |
|
| 5205 OscarData *od = (OscarData *)gc->proto_data; |
|
| 5206 GaimConversation *conv = NULL; |
|
| 5207 struct chat_connection *c = NULL; |
|
| 5208 char *buf, *buf2; |
|
| 5209 guint16 charset, charsubset; |
|
| 5210 char *charsetstr = NULL; |
|
| 5211 int len; |
|
| 5212 |
|
| 5213 if (!(conv = gaim_find_chat(gc, id))) |
|
| 5214 return -EINVAL; |
|
| 5215 |
|
| 5216 if (!(c = find_oscar_chat_by_conv(gc, conv))) |
|
| 5217 return -EINVAL; |
|
| 5218 |
|
| 5219 buf = gaim_strdup_withhtml(message); |
|
| 5220 len = strlen(buf); |
|
| 5221 |
|
| 5222 if (strstr(buf, "<IMG ")) |
|
| 5223 gaim_conversation_write(conv, "", |
|
| 5224 _("Your IM Image was not sent. " |
|
| 5225 "You cannot send IM Images in AIM chats."), |
|
| 5226 GAIM_MESSAGE_ERROR, time(NULL)); |
|
| 5227 |
|
| 5228 gaim_plugin_oscar_convert_to_best_encoding(gc, NULL, buf, &buf2, &len, &charset, &charsubset); |
|
| 5229 /* |
|
| 5230 * Evan S. suggested that maxvis really does mean "number of |
|
| 5231 * visible characters" and not "number of bytes" |
|
| 5232 */ |
|
| 5233 if ((len > c->maxlen) || (len > c->maxvis)) { |
|
| 5234 g_free(buf2); |
|
| 5235 return -E2BIG; |
|
| 5236 } |
|
| 5237 |
|
| 5238 if (charset == AIM_CHARSET_ASCII) |
|
| 5239 charsetstr = "us-ascii"; |
|
| 5240 else if (charset == AIM_CHARSET_UNICODE) |
|
| 5241 charsetstr = "unicode-2-0"; |
|
| 5242 else if (charset == AIM_CHARSET_CUSTOM) |
|
| 5243 charsetstr = "iso-8859-1"; |
|
| 5244 aim_chat_send_im(od, c->conn, 0, buf2, len, charsetstr, "en"); |
|
| 5245 g_free(buf2); |
|
| 5246 |
|
| 5247 return 0; |
|
| 5248 } |
|
| 5249 |
|
| 5250 static const char *oscar_list_icon(GaimAccount *a, GaimBuddy *b) |
|
| 5251 { |
|
| 5252 if ((b == NULL) || (b->name == NULL) || aim_sn_is_sms(b->name)) |
|
| 5253 { |
|
| 5254 if (a != NULL && aim_sn_is_icq(gaim_account_get_username(a))) |
|
| 5255 return "icq"; |
|
| 5256 else |
|
| 5257 return "aim"; |
|
| 5258 } |
|
| 5259 |
|
| 5260 if (aim_sn_is_icq(b->name)) |
|
| 5261 return "icq"; |
|
| 5262 return "aim"; |
|
| 5263 } |
|
| 5264 |
|
| 5265 static void oscar_list_emblems(GaimBuddy *b, const char **se, const char **sw, const char **nw, const char **ne) |
|
| 5266 { |
|
| 5267 GaimConnection *gc = NULL; |
|
| 5268 OscarData *od = NULL; |
|
| 5269 GaimAccount *account = NULL; |
|
| 5270 GaimPresence *presence; |
|
| 5271 GaimStatus *status; |
|
| 5272 const char *status_id; |
|
| 5273 char *emblems[4] = {NULL,NULL,NULL,NULL}; |
|
| 5274 int i = 0; |
|
| 5275 aim_userinfo_t *userinfo = NULL; |
|
| 5276 |
|
| 5277 account = b->account; |
|
| 5278 if (account != NULL) |
|
| 5279 gc = account->gc; |
|
| 5280 if (gc != NULL) |
|
| 5281 od = gc->proto_data; |
|
| 5282 if (od != NULL) |
|
| 5283 userinfo = aim_locate_finduserinfo(od, b->name); |
|
| 5284 |
|
| 5285 presence = gaim_buddy_get_presence(b); |
|
| 5286 status = gaim_presence_get_active_status(presence); |
|
| 5287 status_id = gaim_status_get_id(status); |
|
| 5288 |
|
| 5289 if (gaim_presence_is_online(presence) == FALSE) { |
|
| 5290 char *gname; |
|
| 5291 if ((b->name) && (od) && (od->ssi.received_data) && |
|
| 5292 (gname = aim_ssi_itemlist_findparentname(od->ssi.local, b->name)) && |
|
| 5293 (aim_ssi_waitingforauth(od->ssi.local, gname, b->name))) { |
|
| 5294 emblems[i++] = "notauthorized"; |
|
| 5295 } else { |
|
| 5296 emblems[i++] = "offline"; |
|
| 5297 } |
|
| 5298 } |
|
| 5299 |
|
| 5300 if (b->name && aim_sn_is_icq(b->name)) { |
|
| 5301 if (!strcmp(status_id, OSCAR_STATUS_ID_INVISIBLE)) |
|
| 5302 emblems[i++] = "invisible"; |
|
| 5303 else if (!strcmp(status_id, OSCAR_STATUS_ID_FREE4CHAT)) |
|
| 5304 emblems[i++] = "freeforchat"; |
|
| 5305 else if (!strcmp(status_id, OSCAR_STATUS_ID_DND)) |
|
| 5306 emblems[i++] = "dnd"; |
|
| 5307 else if (!strcmp(status_id, OSCAR_STATUS_ID_NA)) |
|
| 5308 emblems[i++] = "unavailable"; |
|
| 5309 else if (!strcmp(status_id, OSCAR_STATUS_ID_OCCUPIED)) |
|
| 5310 emblems[i++] = "occupied"; |
|
| 5311 else if (!strcmp(status_id, OSCAR_STATUS_ID_AWAY)) |
|
| 5312 emblems[i++] = "away"; |
|
| 5313 } else if (!strcmp(status_id, OSCAR_STATUS_ID_AWAY)) { |
|
| 5314 emblems[i++] = "away"; |
|
| 5315 } |
|
| 5316 |
|
| 5317 if (userinfo != NULL ) { |
|
| 5318 /* if (userinfo->flags & AIM_FLAG_UNCONFIRMED) |
|
| 5319 emblems[i++] = "unconfirmed"; */ |
|
| 5320 if ((i < 4) && userinfo->flags & AIM_FLAG_ADMINISTRATOR) |
|
| 5321 emblems[i++] = "admin"; |
|
| 5322 if ((i < 4) && userinfo->flags & AIM_FLAG_AOL) |
|
| 5323 emblems[i++] = "aol"; |
|
| 5324 if ((i < 4) && userinfo->flags & AIM_FLAG_WIRELESS) |
|
| 5325 emblems[i++] = "wireless"; |
|
| 5326 if ((i < 4) && userinfo->flags & AIM_FLAG_ACTIVEBUDDY) |
|
| 5327 emblems[i++] = "activebuddy"; |
|
| 5328 |
|
| 5329 if ((i < 4) && (userinfo->capabilities & OSCAR_CAPABILITY_HIPTOP)) |
|
| 5330 emblems[i++] = "hiptop"; |
|
| 5331 |
|
| 5332 if ((i < 4) && (userinfo->capabilities & OSCAR_CAPABILITY_SECUREIM)) |
|
| 5333 emblems[i++] = "secure"; |
|
| 5334 } |
|
| 5335 |
|
| 5336 *se = emblems[0]; |
|
| 5337 *sw = emblems[1]; |
|
| 5338 *nw = emblems[2]; |
|
| 5339 *ne = emblems[3]; |
|
| 5340 } |
|
| 5341 |
|
| 5342 static void oscar_tooltip_text(GaimBuddy *b, GString *str, gboolean full) { |
|
| 5343 GaimConnection *gc = b->account->gc; |
|
| 5344 OscarData *od = gc->proto_data; |
|
| 5345 aim_userinfo_t *userinfo = aim_locate_finduserinfo(od, b->name); |
|
| 5346 |
|
| 5347 if (GAIM_BUDDY_IS_ONLINE(b)) { |
|
| 5348 GaimPresence *presence; |
|
| 5349 GaimStatus *status; |
|
| 5350 const char *message; |
|
| 5351 |
|
| 5352 if (full) |
|
| 5353 oscar_string_append_info(gc, str, "\n", b, userinfo); |
|
| 5354 |
|
| 5355 presence = gaim_buddy_get_presence(b); |
|
| 5356 status = gaim_presence_get_active_status(presence); |
|
| 5357 message = gaim_status_get_attr_string(status, "message"); |
|
| 5358 |
|
| 5359 if (gaim_status_is_available(status)) |
|
| 5360 { |
|
| 5361 if (message != NULL) |
|
| 5362 { |
|
| 5363 /* Available status messages are plain text */ |
|
| 5364 gchar *tmp; |
|
| 5365 tmp = g_markup_escape_text(message, -1); |
|
| 5366 g_string_append_printf(str, "\n<b>%s:</b> %s", _("Message"), tmp); |
|
| 5367 g_free(tmp); |
|
| 5368 } |
|
| 5369 } |
|
| 5370 else |
|
| 5371 { |
|
| 5372 if (message != NULL) |
|
| 5373 { |
|
| 5374 /* Away messages are HTML */ |
|
| 5375 gchar *tmp1, *tmp2; |
|
| 5376 tmp2 = gaim_markup_strip_html(message); |
|
| 5377 tmp1 = g_markup_escape_text(tmp2, -1); |
|
| 5378 g_free(tmp2); |
|
| 5379 tmp2 = gaim_str_sub_away_formatters(tmp1, gaim_account_get_username(gaim_connection_get_account(gc))); |
|
| 5380 g_free(tmp1); |
|
| 5381 g_string_append_printf(str, "\n<b>%s:</b> %s", _("Message"), tmp2); |
|
| 5382 g_free(tmp2); |
|
| 5383 } |
|
| 5384 else |
|
| 5385 { |
|
| 5386 g_string_append_printf(str, "\n<b>%s:</b> %s", _("Message"), _("<i>(retrieving)</i>")); |
|
| 5387 } |
|
| 5388 } |
|
| 5389 } |
|
| 5390 } |
|
| 5391 |
|
| 5392 static char *oscar_status_text(GaimBuddy *b) |
|
| 5393 { |
|
| 5394 GaimConnection *gc; |
|
| 5395 GaimAccount *account; |
|
| 5396 OscarData *od; |
|
| 5397 const GaimPresence *presence; |
|
| 5398 const GaimStatus *status; |
|
| 5399 const char *id; |
|
| 5400 const char *message; |
|
| 5401 gchar *ret = NULL; |
|
| 5402 |
|
| 5403 gc = gaim_account_get_connection(gaim_buddy_get_account(b)); |
|
| 5404 account = gaim_connection_get_account(gc); |
|
| 5405 od = gc->proto_data; |
|
| 5406 presence = gaim_buddy_get_presence(b); |
|
| 5407 status = gaim_presence_get_active_status(presence); |
|
| 5408 id = gaim_status_get_id(status); |
|
| 5409 |
|
| 5410 if (!gaim_presence_is_online(presence)) |
|
| 5411 { |
|
| 5412 char *gname = aim_ssi_itemlist_findparentname(od->ssi.local, b->name); |
|
| 5413 if (aim_ssi_waitingforauth(od->ssi.local, gname, b->name)) |
|
| 5414 ret = g_strdup(_("Not Authorized")); |
|
| 5415 else |
|
| 5416 ret = g_strdup(_("Offline")); |
|
| 5417 } |
|
| 5418 else if (gaim_status_is_available(status) && !strcmp(id, OSCAR_STATUS_ID_AVAILABLE)) |
|
| 5419 { |
|
| 5420 /* Available */ |
|
| 5421 message = gaim_status_get_attr_string(status, "message"); |
|
| 5422 if (message != NULL) |
|
| 5423 { |
|
| 5424 ret = g_markup_escape_text(message, -1); |
|
| 5425 gaim_util_chrreplace(ret, '\n', ' '); |
|
| 5426 } |
|
| 5427 } |
|
| 5428 else if (!gaim_status_is_available(status) && !strcmp(id, OSCAR_STATUS_ID_AWAY)) |
|
| 5429 { |
|
| 5430 /* Away */ |
|
| 5431 message = gaim_status_get_attr_string(status, "message"); |
|
| 5432 if (message != NULL) |
|
| 5433 { |
|
| 5434 gchar *tmp1, *tmp2; |
|
| 5435 tmp1 = gaim_markup_strip_html(message); |
|
| 5436 gaim_util_chrreplace(tmp1, '\n', ' '); |
|
| 5437 tmp2 = g_markup_escape_text(tmp1, -1); |
|
| 5438 ret = gaim_str_sub_away_formatters(tmp2, gaim_account_get_username(account)); |
|
| 5439 g_free(tmp1); |
|
| 5440 g_free(tmp2); |
|
| 5441 } |
|
| 5442 else |
|
| 5443 { |
|
| 5444 ret = g_strdup(_("Away")); |
|
| 5445 } |
|
| 5446 } |
|
| 5447 else |
|
| 5448 ret = g_strdup(gaim_status_get_name(status)); |
|
| 5449 |
|
| 5450 return ret; |
|
| 5451 } |
|
| 5452 |
|
| 5453 |
|
| 5454 static int oscar_icon_req(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) { |
|
| 5455 GaimConnection *gc = od->gc; |
|
| 5456 va_list ap; |
|
| 5457 guint16 type; |
|
| 5458 guint8 flags = 0, length = 0; |
|
| 5459 guchar *md5 = NULL; |
|
| 5460 |
|
| 5461 va_start(ap, fr); |
|
| 5462 type = va_arg(ap, int); |
|
| 5463 |
|
| 5464 switch(type) { |
|
| 5465 case 0x0000: |
|
| 5466 case 0x0001: { |
|
| 5467 flags = va_arg(ap, int); |
|
| 5468 length = va_arg(ap, int); |
|
| 5469 md5 = va_arg(ap, guchar *); |
|
| 5470 |
|
| 5471 if (flags == 0x41) { |
|
| 5472 if (!flap_connection_getbytype(od, SNAC_FAMILY_BART) && !od->iconconnecting) { |
|
| 5473 od->iconconnecting = TRUE; |
|
| 5474 od->set_icon = TRUE; |
|
| 5475 aim_reqservice(od, SNAC_FAMILY_BART); |
|
| 5476 } else { |
|
| 5477 struct stat st; |
|
| 5478 char *iconfile = gaim_buddy_icons_get_full_path(gaim_account_get_buddy_icon(gaim_connection_get_account(gc))); |
|
| 5479 if (iconfile == NULL) { |
|
| 5480 aim_ssi_delicon(od); |
|
| 5481 } else if (!g_stat(iconfile, &st)) { |
|
| 5482 guchar *buf = g_malloc(st.st_size); |
|
| 5483 FILE *file = g_fopen(iconfile, "rb"); |
|
| 5484 if (file) { |
|
| 5485 /* XXX - Use g_file_get_contents()? */ |
|
| 5486 fread(buf, 1, st.st_size, file); |
|
| 5487 fclose(file); |
|
| 5488 gaim_debug_info("oscar", |
|
| 5489 "Uploading icon to icon server\n"); |
|
| 5490 aim_bart_upload(od, buf, st.st_size); |
|
| 5491 } else |
|
| 5492 gaim_debug_error("oscar", |
|
| 5493 "Can't open buddy icon file!\n"); |
|
| 5494 g_free(buf); |
|
| 5495 } else { |
|
| 5496 gaim_debug_error("oscar", |
|
| 5497 "Can't stat buddy icon file!\n"); |
|
| 5498 } |
|
| 5499 g_free(iconfile); |
|
| 5500 } |
|
| 5501 } else if (flags == 0x81) { |
|
| 5502 char *iconfile = gaim_buddy_icons_get_full_path(gaim_account_get_buddy_icon(gaim_connection_get_account(gc))); |
|
| 5503 if (iconfile == NULL) |
|
| 5504 aim_ssi_delicon(od); |
|
| 5505 else { |
|
| 5506 aim_ssi_seticon(od, md5, length); |
|
| 5507 g_free(iconfile); |
|
| 5508 } |
|
| 5509 } |
|
| 5510 } break; |
|
| 5511 |
|
| 5512 case 0x0002: { /* We just set an "available" message? */ |
|
| 5513 } break; |
|
| 5514 } |
|
| 5515 |
|
| 5516 va_end(ap); |
|
| 5517 |
|
| 5518 return 0; |
|
| 5519 } |
|
| 5520 |
|
| 5521 static void oscar_set_permit_deny(GaimConnection *gc) { |
|
| 5522 GaimAccount *account = gaim_connection_get_account(gc); |
|
| 5523 OscarData *od = (OscarData *)gc->proto_data; |
|
| 5524 |
|
| 5525 if (od->ssi.received_data) { |
|
| 5526 switch (account->perm_deny) { |
|
| 5527 case GAIM_PRIVACY_ALLOW_ALL: |
|
| 5528 aim_ssi_setpermdeny(od, 0x01, 0xffffffff); |
|
| 5529 break; |
|
| 5530 case GAIM_PRIVACY_ALLOW_BUDDYLIST: |
|
| 5531 aim_ssi_setpermdeny(od, 0x05, 0xffffffff); |
|
| 5532 break; |
|
| 5533 case GAIM_PRIVACY_ALLOW_USERS: |
|
| 5534 aim_ssi_setpermdeny(od, 0x03, 0xffffffff); |
|
| 5535 break; |
|
| 5536 case GAIM_PRIVACY_DENY_ALL: |
|
| 5537 aim_ssi_setpermdeny(od, 0x02, 0xffffffff); |
|
| 5538 break; |
|
| 5539 case GAIM_PRIVACY_DENY_USERS: |
|
| 5540 aim_ssi_setpermdeny(od, 0x04, 0xffffffff); |
|
| 5541 break; |
|
| 5542 default: |
|
| 5543 aim_ssi_setpermdeny(od, 0x01, 0xffffffff); |
|
| 5544 break; |
|
| 5545 } |
|
| 5546 } |
|
| 5547 } |
|
| 5548 |
|
| 5549 static void oscar_add_permit(GaimConnection *gc, const char *who) { |
|
| 5550 OscarData *od = (OscarData *)gc->proto_data; |
|
| 5551 gaim_debug_info("oscar", "ssi: About to add a permit\n"); |
|
| 5552 if (od->ssi.received_data) |
|
| 5553 aim_ssi_addpermit(od, who); |
|
| 5554 } |
|
| 5555 |
|
| 5556 static void oscar_add_deny(GaimConnection *gc, const char *who) { |
|
| 5557 OscarData *od = (OscarData *)gc->proto_data; |
|
| 5558 gaim_debug_info("oscar", "ssi: About to add a deny\n"); |
|
| 5559 if (od->ssi.received_data) |
|
| 5560 aim_ssi_adddeny(od, who); |
|
| 5561 } |
|
| 5562 |
|
| 5563 static void oscar_rem_permit(GaimConnection *gc, const char *who) { |
|
| 5564 OscarData *od = (OscarData *)gc->proto_data; |
|
| 5565 gaim_debug_info("oscar", "ssi: About to delete a permit\n"); |
|
| 5566 if (od->ssi.received_data) |
|
| 5567 aim_ssi_delpermit(od, who); |
|
| 5568 } |
|
| 5569 |
|
| 5570 static void oscar_rem_deny(GaimConnection *gc, const char *who) { |
|
| 5571 OscarData *od = (OscarData *)gc->proto_data; |
|
| 5572 gaim_debug_info("oscar", "ssi: About to delete a deny\n"); |
|
| 5573 if (od->ssi.received_data) |
|
| 5574 aim_ssi_deldeny(od, who); |
|
| 5575 } |
|
| 5576 |
|
| 5577 static GList * |
|
| 5578 oscar_status_types(GaimAccount *account) |
|
| 5579 { |
|
| 5580 gboolean is_icq; |
|
| 5581 GList *status_types = NULL; |
|
| 5582 GaimStatusType *type; |
|
| 5583 |
|
| 5584 g_return_val_if_fail(account != NULL, NULL); |
|
| 5585 |
|
| 5586 /* Used to flag some statuses as "user settable" or not */ |
|
| 5587 is_icq = aim_sn_is_icq(gaim_account_get_username(account)); |
|
| 5588 |
|
| 5589 /* Common status types */ |
|
| 5590 /* Really the available message should only be settable for AIM accounts */ |
|
| 5591 type = gaim_status_type_new_with_attrs(GAIM_STATUS_AVAILABLE, |
|
| 5592 OSCAR_STATUS_ID_AVAILABLE, |
|
| 5593 NULL, TRUE, TRUE, FALSE, |
|
| 5594 "message", _("Message"), |
|
| 5595 gaim_value_new(GAIM_TYPE_STRING), NULL); |
|
| 5596 status_types = g_list_append(status_types, type); |
|
| 5597 |
|
| 5598 type = gaim_status_type_new_full(GAIM_STATUS_AVAILABLE, |
|
| 5599 OSCAR_STATUS_ID_FREE4CHAT, |
|
| 5600 _("Free For Chat"), TRUE, is_icq, FALSE); |
|
| 5601 status_types = g_list_append(status_types, type); |
|
| 5602 |
|
| 5603 type = gaim_status_type_new_with_attrs(GAIM_STATUS_AWAY, |
|
| 5604 OSCAR_STATUS_ID_AWAY, |
|
| 5605 NULL, TRUE, TRUE, FALSE, |
|
| 5606 "message", _("Message"), |
|
| 5607 gaim_value_new(GAIM_TYPE_STRING), NULL); |
|
| 5608 status_types = g_list_append(status_types, type); |
|
| 5609 |
|
| 5610 type = gaim_status_type_new_full(GAIM_STATUS_INVISIBLE, |
|
| 5611 OSCAR_STATUS_ID_INVISIBLE, |
|
| 5612 NULL, TRUE, TRUE, FALSE); |
|
| 5613 status_types = g_list_append(status_types, type); |
|
| 5614 |
|
| 5615 /* ICQ-specific status types */ |
|
| 5616 type = gaim_status_type_new_with_attrs(GAIM_STATUS_UNAVAILABLE, |
|
| 5617 OSCAR_STATUS_ID_OCCUPIED, |
|
| 5618 _("Occupied"), TRUE, is_icq, FALSE, |
|
| 5619 "message", _("Message"), |
|
| 5620 gaim_value_new(GAIM_TYPE_STRING), NULL); |
|
| 5621 status_types = g_list_append(status_types, type); |
|
| 5622 |
|
| 5623 type = gaim_status_type_new_with_attrs(GAIM_STATUS_EXTENDED_AWAY, |
|
| 5624 OSCAR_STATUS_ID_DND, |
|
| 5625 _("Do Not Disturb"), TRUE, is_icq, FALSE, |
|
| 5626 "message", _("Message"), |
|
| 5627 gaim_value_new(GAIM_TYPE_STRING), NULL); |
|
| 5628 status_types = g_list_append(status_types, type); |
|
| 5629 |
|
| 5630 type = gaim_status_type_new_with_attrs(GAIM_STATUS_EXTENDED_AWAY, |
|
| 5631 OSCAR_STATUS_ID_NA, |
|
| 5632 _("Not Available"), TRUE, is_icq, FALSE, |
|
| 5633 "message", _("Message"), |
|
| 5634 gaim_value_new(GAIM_TYPE_STRING), NULL); |
|
| 5635 status_types = g_list_append(status_types, type); |
|
| 5636 |
|
| 5637 type = gaim_status_type_new_full(GAIM_STATUS_OFFLINE, |
|
| 5638 OSCAR_STATUS_ID_OFFLINE, |
|
| 5639 NULL, TRUE, TRUE, FALSE); |
|
| 5640 status_types = g_list_append(status_types, type); |
|
| 5641 |
|
| 5642 return status_types; |
|
| 5643 } |
|
| 5644 |
|
| 5645 static void oscar_ssi_editcomment(struct name_data *data, const char *text) { |
|
| 5646 GaimConnection *gc = data->gc; |
|
| 5647 OscarData *od = gc->proto_data; |
|
| 5648 GaimBuddy *b; |
|
| 5649 GaimGroup *g; |
|
| 5650 |
|
| 5651 if (!(b = gaim_find_buddy(gaim_connection_get_account(data->gc), data->name))) { |
|
| 5652 oscar_free_name_data(data); |
|
| 5653 return; |
|
| 5654 } |
|
| 5655 |
|
| 5656 if (!(g = gaim_buddy_get_group(b))) { |
|
| 5657 oscar_free_name_data(data); |
|
| 5658 return; |
|
| 5659 } |
|
| 5660 |
|
| 5661 aim_ssi_editcomment(od, g->name, data->name, text); |
|
| 5662 |
|
| 5663 if (!aim_sncmp(data->name, gc->account->username)) |
|
| 5664 gaim_check_comment(od, text); |
|
| 5665 |
|
| 5666 oscar_free_name_data(data); |
|
| 5667 } |
|
| 5668 |
|
| 5669 static void oscar_buddycb_edit_comment(GaimBlistNode *node, gpointer ignore) { |
|
| 5670 |
|
| 5671 GaimBuddy *buddy; |
|
| 5672 GaimConnection *gc; |
|
| 5673 OscarData *od; |
|
| 5674 struct name_data *data; |
|
| 5675 GaimGroup *g; |
|
| 5676 char *comment; |
|
| 5677 gchar *comment_utf8; |
|
| 5678 gchar *title; |
|
| 5679 |
|
| 5680 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); |
|
| 5681 |
|
| 5682 buddy = (GaimBuddy *) node; |
|
| 5683 gc = gaim_account_get_connection(buddy->account); |
|
| 5684 od = gc->proto_data; |
|
| 5685 |
|
| 5686 data = g_new(struct name_data, 1); |
|
| 5687 |
|
| 5688 if (!(g = gaim_buddy_get_group(buddy))) |
|
| 5689 return; |
|
| 5690 comment = aim_ssi_getcomment(od->ssi.local, g->name, buddy->name); |
|
| 5691 comment_utf8 = comment ? oscar_utf8_try_convert(gc->account, comment) : NULL; |
|
| 5692 |
|
| 5693 data->gc = gc; |
|
| 5694 data->name = g_strdup(buddy->name); |
|
| 5695 data->nick = NULL; |
|
| 5696 |
|
| 5697 title = g_strdup_printf(_("Buddy Comment for %s"), data->name); |
|
| 5698 gaim_request_input(gc, title, _("Buddy Comment:"), NULL, |
|
| 5699 comment_utf8, TRUE, FALSE, NULL, |
|
| 5700 _("OK"), G_CALLBACK(oscar_ssi_editcomment), |
|
| 5701 _("Cancel"), G_CALLBACK(oscar_free_name_data), |
|
| 5702 data); |
|
| 5703 g_free(title); |
|
| 5704 |
|
| 5705 g_free(comment); |
|
| 5706 g_free(comment_utf8); |
|
| 5707 } |
|
| 5708 |
|
| 5709 static void |
|
| 5710 oscar_ask_directim_yes_cb(struct oscar_ask_directim_data *data) |
|
| 5711 { |
|
| 5712 peer_connection_propose(data->od, OSCAR_CAPABILITY_DIRECTIM, data->who); |
|
| 5713 g_free(data->who); |
|
| 5714 g_free(data); |
|
| 5715 } |
|
| 5716 |
|
| 5717 static void |
|
| 5718 oscar_ask_directim_no_cb(struct oscar_ask_directim_data *data) |
|
| 5719 { |
|
| 5720 g_free(data->who); |
|
| 5721 g_free(data); |
|
| 5722 } |
|
| 5723 |
|
| 5724 /* This is called from right-click menu on a buddy node. */ |
|
| 5725 static void |
|
| 5726 oscar_ask_directim(gpointer object, gpointer ignored) |
|
| 5727 { |
|
| 5728 GaimBlistNode *node; |
|
| 5729 GaimBuddy *buddy; |
|
| 5730 GaimConnection *gc; |
|
| 5731 gchar *buf; |
|
| 5732 struct oscar_ask_directim_data *data; |
|
| 5733 |
|
| 5734 node = object; |
|
| 5735 |
|
| 5736 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); |
|
| 5737 |
|
| 5738 buddy = (GaimBuddy *)node; |
|
| 5739 gc = gaim_account_get_connection(buddy->account); |
|
| 5740 |
|
| 5741 data = g_new0(struct oscar_ask_directim_data, 1); |
|
| 5742 data->who = g_strdup(buddy->name); |
|
| 5743 data->od = gc->proto_data; |
|
| 5744 buf = g_strdup_printf(_("You have selected to open a Direct IM connection with %s."), |
|
| 5745 buddy->name); |
|
| 5746 |
|
| 5747 gaim_request_action(gc, NULL, buf, |
|
| 5748 _("Because this reveals your IP address, it " |
|
| 5749 "may be considered a security risk. Do you " |
|
| 5750 "wish to continue?"), |
|
| 5751 0, data, 2, |
|
| 5752 _("_Connect"), G_CALLBACK(oscar_ask_directim_yes_cb), |
|
| 5753 _("Cancel"), G_CALLBACK(oscar_ask_directim_no_cb)); |
|
| 5754 g_free(buf); |
|
| 5755 } |
|
| 5756 |
|
| 5757 static void |
|
| 5758 oscar_get_aim_info_cb(GaimBlistNode *node, gpointer ignore) |
|
| 5759 { |
|
| 5760 GaimBuddy *buddy; |
|
| 5761 GaimConnection *gc; |
|
| 5762 |
|
| 5763 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); |
|
| 5764 |
|
| 5765 buddy = (GaimBuddy *)node; |
|
| 5766 gc = gaim_account_get_connection(buddy->account); |
|
| 5767 |
|
| 5768 aim_locate_getinfoshort(gc->proto_data, gaim_buddy_get_name(buddy), 0x00000003); |
|
| 5769 } |
|
| 5770 |
|
| 5771 static GList *oscar_buddy_menu(GaimBuddy *buddy) { |
|
| 5772 |
|
| 5773 GaimConnection *gc; |
|
| 5774 OscarData *od; |
|
| 5775 GList *m; |
|
| 5776 GaimMenuAction *act; |
|
| 5777 aim_userinfo_t *userinfo; |
|
| 5778 |
|
| 5779 gc = gaim_account_get_connection(buddy->account); |
|
| 5780 od = gc->proto_data; |
|
| 5781 userinfo = aim_locate_finduserinfo(od, buddy->name); |
|
| 5782 m = NULL; |
|
| 5783 |
|
| 5784 if (od->icq && aim_sn_is_icq(gaim_buddy_get_name(buddy))) |
|
| 5785 { |
|
| 5786 act = gaim_menu_action_new(_("Get AIM Info"), |
|
| 5787 GAIM_CALLBACK(oscar_get_aim_info_cb), |
|
| 5788 NULL, NULL); |
|
| 5789 m = g_list_append(m, act); |
|
| 5790 } |
|
| 5791 |
|
| 5792 act = gaim_menu_action_new(_("Edit Buddy Comment"), |
|
| 5793 GAIM_CALLBACK(oscar_buddycb_edit_comment), |
|
| 5794 NULL, NULL); |
|
| 5795 m = g_list_append(m, act); |
|
| 5796 |
|
| 5797 #if 0 |
|
| 5798 if (od->icq) |
|
| 5799 { |
|
| 5800 act = gaim_menu_action_new(_("Get Status Msg"), |
|
| 5801 GAIM_CALLBACK(oscar_get_icqstatusmsg), |
|
| 5802 NULL, NULL); |
|
| 5803 m = g_list_append(m, act); |
|
| 5804 } |
|
| 5805 #endif |
|
| 5806 |
|
| 5807 if (userinfo && |
|
| 5808 aim_sncmp(gaim_account_get_username(buddy->account), buddy->name) && |
|
| 5809 GAIM_BUDDY_IS_ONLINE(buddy)) |
|
| 5810 { |
|
| 5811 if (userinfo->capabilities & OSCAR_CAPABILITY_DIRECTIM) |
|
| 5812 { |
|
| 5813 act = gaim_menu_action_new(_("Direct IM"), |
|
| 5814 GAIM_CALLBACK(oscar_ask_directim), |
|
| 5815 NULL, NULL); |
|
| 5816 m = g_list_append(m, act); |
|
| 5817 } |
|
| 5818 #if 0 |
|
| 5819 /* TODO: This menu item should be added by the core */ |
|
| 5820 if (userinfo->capabilities & OSCAR_CAPABILITY_GETFILE) { |
|
| 5821 act = gaim_menu_action_new(_("Get File"), |
|
| 5822 GAIM_CALLBACK(oscar_ask_getfile), |
|
| 5823 NULL, NULL); |
|
| 5824 m = g_list_append(m, act); |
|
| 5825 } |
|
| 5826 #endif |
|
| 5827 } |
|
| 5828 |
|
| 5829 if (od->ssi.received_data) |
|
| 5830 { |
|
| 5831 char *gname; |
|
| 5832 gname = aim_ssi_itemlist_findparentname(od->ssi.local, buddy->name); |
|
| 5833 if (gname && aim_ssi_waitingforauth(od->ssi.local, gname, buddy->name)) |
|
| 5834 { |
|
| 5835 act = gaim_menu_action_new(_("Re-request Authorization"), |
|
| 5836 GAIM_CALLBACK(gaim_auth_sendrequest_menu), |
|
| 5837 NULL, NULL); |
|
| 5838 m = g_list_append(m, act); |
|
| 5839 } |
|
| 5840 } |
|
| 5841 |
|
| 5842 return m; |
|
| 5843 } |
|
| 5844 |
|
| 5845 |
|
| 5846 static GList *oscar_blist_node_menu(GaimBlistNode *node) { |
|
| 5847 if(GAIM_BLIST_NODE_IS_BUDDY(node)) { |
|
| 5848 return oscar_buddy_menu((GaimBuddy *) node); |
|
| 5849 } else { |
|
| 5850 return NULL; |
|
| 5851 } |
|
| 5852 } |
|
| 5853 |
|
| 5854 static void |
|
| 5855 oscar_icq_privacy_opts(GaimConnection *gc, GaimRequestFields *fields) |
|
| 5856 { |
|
| 5857 OscarData *od = gc->proto_data; |
|
| 5858 GaimAccount *account = gaim_connection_get_account(gc); |
|
| 5859 GaimRequestField *f; |
|
| 5860 gboolean auth, web_aware; |
|
| 5861 |
|
| 5862 f = gaim_request_fields_get_field(fields, "authorization"); |
|
| 5863 auth = gaim_request_field_bool_get_value(f); |
|
| 5864 |
|
| 5865 f = gaim_request_fields_get_field(fields, "web_aware"); |
|
| 5866 web_aware = gaim_request_field_bool_get_value(f); |
|
| 5867 |
|
| 5868 gaim_account_set_bool(account, "authorization", auth); |
|
| 5869 gaim_account_set_bool(account, "web_aware", web_aware); |
|
| 5870 |
|
| 5871 oscar_set_extendedstatus(gc); |
|
| 5872 aim_icq_setsecurity(od, auth, web_aware); |
|
| 5873 } |
|
| 5874 |
|
| 5875 static void |
|
| 5876 oscar_show_icq_privacy_opts(GaimPluginAction *action) |
|
| 5877 { |
|
| 5878 GaimConnection *gc = (GaimConnection *) action->context; |
|
| 5879 GaimAccount *account = gaim_connection_get_account(gc); |
|
| 5880 GaimRequestFields *fields; |
|
| 5881 GaimRequestFieldGroup *g; |
|
| 5882 GaimRequestField *f; |
|
| 5883 gboolean auth, web_aware; |
|
| 5884 |
|
| 5885 auth = gaim_account_get_bool(account, "authorization", OSCAR_DEFAULT_AUTHORIZATION); |
|
| 5886 web_aware = gaim_account_get_bool(account, "web_aware", OSCAR_DEFAULT_WEB_AWARE); |
|
| 5887 |
|
| 5888 fields = gaim_request_fields_new(); |
|
| 5889 |
|
| 5890 g = gaim_request_field_group_new(NULL); |
|
| 5891 |
|
| 5892 f = gaim_request_field_bool_new("authorization", _("Require authorization"), auth); |
|
| 5893 gaim_request_field_group_add_field(g, f); |
|
| 5894 |
|
| 5895 f = gaim_request_field_bool_new("web_aware", _("Web aware (enabling this will cause you to receive SPAM!)"), web_aware); |
|
| 5896 gaim_request_field_group_add_field(g, f); |
|
| 5897 |
|
| 5898 gaim_request_fields_add_group(fields, g); |
|
| 5899 |
|
| 5900 gaim_request_fields(gc, _("ICQ Privacy Options"), _("ICQ Privacy Options"), |
|
| 5901 NULL, fields, |
|
| 5902 _("OK"), G_CALLBACK(oscar_icq_privacy_opts), |
|
| 5903 _("Cancel"), NULL, gc); |
|
| 5904 } |
|
| 5905 |
|
| 5906 static void oscar_format_screenname(GaimConnection *gc, const char *nick) { |
|
| 5907 OscarData *od = gc->proto_data; |
|
| 5908 if (!aim_sncmp(gaim_account_get_username(gaim_connection_get_account(gc)), nick)) { |
|
| 5909 if (!flap_connection_getbytype(od, SNAC_FAMILY_ADMIN)) { |
|
| 5910 od->setnick = TRUE; |
|
| 5911 od->newsn = g_strdup(nick); |
|
| 5912 aim_reqservice(od, SNAC_FAMILY_ADMIN); |
|
| 5913 } else { |
|
| 5914 aim_admin_setnick(od, flap_connection_getbytype(od, SNAC_FAMILY_ADMIN), nick); |
|
| 5915 } |
|
| 5916 } else { |
|
| 5917 gaim_notify_error(gc, NULL, _("The new formatting is invalid."), |
|
| 5918 _("Screen name formatting can change only capitalization and whitespace.")); |
|
| 5919 } |
|
| 5920 } |
|
| 5921 |
|
| 5922 static void oscar_show_format_screenname(GaimPluginAction *action) |
|
| 5923 { |
|
| 5924 GaimConnection *gc = (GaimConnection *) action->context; |
|
| 5925 gaim_request_input(gc, NULL, _("New screen name formatting:"), NULL, |
|
| 5926 gaim_connection_get_display_name(gc), FALSE, FALSE, NULL, |
|
| 5927 _("OK"), G_CALLBACK(oscar_format_screenname), |
|
| 5928 _("Cancel"), NULL, |
|
| 5929 gc); |
|
| 5930 } |
|
| 5931 |
|
| 5932 static void oscar_confirm_account(GaimPluginAction *action) |
|
| 5933 { |
|
| 5934 GaimConnection *gc; |
|
| 5935 OscarData *od; |
|
| 5936 FlapConnection *conn; |
|
| 5937 |
|
| 5938 gc = (GaimConnection *)action->context; |
|
| 5939 od = gc->proto_data; |
|
| 5940 |
|
| 5941 conn = flap_connection_getbytype(od, SNAC_FAMILY_ADMIN); |
|
| 5942 if (conn != NULL) { |
|
| 5943 aim_admin_reqconfirm(od, conn); |
|
| 5944 } else { |
|
| 5945 od->conf = TRUE; |
|
| 5946 aim_reqservice(od, SNAC_FAMILY_ADMIN); |
|
| 5947 } |
|
| 5948 } |
|
| 5949 |
|
| 5950 static void oscar_show_email(GaimPluginAction *action) |
|
| 5951 { |
|
| 5952 GaimConnection *gc = (GaimConnection *) action->context; |
|
| 5953 OscarData *od = gc->proto_data; |
|
| 5954 FlapConnection *conn = flap_connection_getbytype(od, SNAC_FAMILY_ADMIN); |
|
| 5955 |
|
| 5956 if (conn) { |
|
| 5957 aim_admin_getinfo(od, conn, 0x11); |
|
| 5958 } else { |
|
| 5959 od->reqemail = TRUE; |
|
| 5960 aim_reqservice(od, SNAC_FAMILY_ADMIN); |
|
| 5961 } |
|
| 5962 } |
|
| 5963 |
|
| 5964 static void oscar_change_email(GaimConnection *gc, const char *email) |
|
| 5965 { |
|
| 5966 OscarData *od = gc->proto_data; |
|
| 5967 FlapConnection *conn = flap_connection_getbytype(od, SNAC_FAMILY_ADMIN); |
|
| 5968 |
|
| 5969 if (conn) { |
|
| 5970 aim_admin_setemail(od, conn, email); |
|
| 5971 } else { |
|
| 5972 od->setemail = TRUE; |
|
| 5973 od->email = g_strdup(email); |
|
| 5974 aim_reqservice(od, SNAC_FAMILY_ADMIN); |
|
| 5975 } |
|
| 5976 } |
|
| 5977 |
|
| 5978 static void oscar_show_change_email(GaimPluginAction *action) |
|
| 5979 { |
|
| 5980 GaimConnection *gc = (GaimConnection *) action->context; |
|
| 5981 gaim_request_input(gc, NULL, _("Change Address To:"), NULL, NULL, |
|
| 5982 FALSE, FALSE, NULL, |
|
| 5983 _("OK"), G_CALLBACK(oscar_change_email), |
|
| 5984 _("Cancel"), NULL, |
|
| 5985 gc); |
|
| 5986 } |
|
| 5987 |
|
| 5988 static void oscar_show_awaitingauth(GaimPluginAction *action) |
|
| 5989 { |
|
| 5990 GaimConnection *gc = (GaimConnection *) action->context; |
|
| 5991 OscarData *od = gc->proto_data; |
|
| 5992 gchar *nombre, *text, *tmp; |
|
| 5993 GaimBlistNode *gnode, *cnode, *bnode; |
|
| 5994 int num=0; |
|
| 5995 |
|
| 5996 text = g_strdup(""); |
|
| 5997 |
|
| 5998 for (gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) { |
|
| 5999 GaimGroup *group = (GaimGroup *)gnode; |
|
| 6000 if(!GAIM_BLIST_NODE_IS_GROUP(gnode)) |
|
| 6001 continue; |
|
| 6002 for (cnode = gnode->child; cnode; cnode = cnode->next) { |
|
| 6003 if(!GAIM_BLIST_NODE_IS_CONTACT(cnode)) |
|
| 6004 continue; |
|
| 6005 for (bnode = cnode->child; bnode; bnode = bnode->next) { |
|
| 6006 GaimBuddy *buddy = (GaimBuddy *)bnode; |
|
| 6007 if(!GAIM_BLIST_NODE_IS_BUDDY(bnode)) |
|
| 6008 continue; |
|
| 6009 if (buddy->account == gc->account && aim_ssi_waitingforauth(od->ssi.local, group->name, buddy->name)) { |
|
| 6010 if (gaim_buddy_get_alias_only(buddy)) |
|
| 6011 nombre = g_strdup_printf(" %s (%s)", buddy->name, gaim_buddy_get_alias_only(buddy)); |
|
| 6012 else |
|
| 6013 nombre = g_strdup_printf(" %s", buddy->name); |
|
| 6014 tmp = g_strdup_printf("%s%s<br>", text, nombre); |
|
| 6015 g_free(text); |
|
| 6016 text = tmp; |
|
| 6017 g_free(nombre); |
|
| 6018 num++; |
|
| 6019 } |
|
| 6020 } |
|
| 6021 } |
|
| 6022 } |
|
| 6023 |
|
| 6024 if (!num) { |
|
| 6025 g_free(text); |
|
| 6026 text = g_strdup(_("<i>you are not waiting for authorization</i>")); |
|
| 6027 } |
|
| 6028 |
|
| 6029 gaim_notify_formatted(gc, NULL, _("You are awaiting authorization from " |
|
| 6030 "the following buddies"), _("You can re-request " |
|
| 6031 "authorization from these buddies by " |
|
| 6032 "right-clicking on them and selecting " |
|
| 6033 "\"Re-request Authorization.\""), text, NULL, NULL); |
|
| 6034 g_free(text); |
|
| 6035 } |
|
| 6036 |
|
| 6037 static void search_by_email_cb(GaimConnection *gc, const char *email) |
|
| 6038 { |
|
| 6039 OscarData *od = (OscarData *)gc->proto_data; |
|
| 6040 |
|
| 6041 aim_search_address(od, email); |
|
| 6042 } |
|
| 6043 |
|
| 6044 static void oscar_show_find_email(GaimPluginAction *action) |
|
| 6045 { |
|
| 6046 GaimConnection *gc = (GaimConnection *) action->context; |
|
| 6047 gaim_request_input(gc, _("Find Buddy by E-Mail"), |
|
| 6048 _("Search for a buddy by e-mail address"), |
|
| 6049 _("Type the e-mail address of the buddy you are " |
|
| 6050 "searching for."), |
|
| 6051 NULL, FALSE, FALSE, NULL, |
|
| 6052 _("Search"), G_CALLBACK(search_by_email_cb), |
|
| 6053 _("Cancel"), NULL, gc); |
|
| 6054 } |
|
| 6055 |
|
| 6056 static void oscar_show_set_info(GaimPluginAction *action) |
|
| 6057 { |
|
| 6058 GaimConnection *gc = (GaimConnection *) action->context; |
|
| 6059 gaim_account_request_change_user_info(gaim_connection_get_account(gc)); |
|
| 6060 } |
|
| 6061 |
|
| 6062 static void oscar_show_set_info_icqurl(GaimPluginAction *action) |
|
| 6063 { |
|
| 6064 GaimConnection *gc = (GaimConnection *) action->context; |
|
| 6065 gaim_notify_uri(gc, "http://www.icq.com/whitepages/user_details.php"); |
|
| 6066 } |
|
| 6067 |
|
| 6068 static void oscar_change_pass(GaimPluginAction *action) |
|
| 6069 { |
|
| 6070 GaimConnection *gc = (GaimConnection *) action->context; |
|
| 6071 gaim_account_request_change_password(gaim_connection_get_account(gc)); |
|
| 6072 } |
|
| 6073 |
|
| 6074 static void oscar_show_chpassurl(GaimPluginAction *action) |
|
| 6075 { |
|
| 6076 GaimConnection *gc = (GaimConnection *) action->context; |
|
| 6077 OscarData *od = gc->proto_data; |
|
| 6078 gchar *substituted = gaim_strreplace(od->authinfo->chpassurl, "%s", gaim_account_get_username(gaim_connection_get_account(gc))); |
|
| 6079 gaim_notify_uri(gc, substituted); |
|
| 6080 g_free(substituted); |
|
| 6081 } |
|
| 6082 |
|
| 6083 static void oscar_show_imforwardingurl(GaimPluginAction *action) |
|
| 6084 { |
|
| 6085 GaimConnection *gc = (GaimConnection *) action->context; |
|
| 6086 gaim_notify_uri(gc, "http://mymobile.aol.com/dbreg/register?action=imf&clientID=1"); |
|
| 6087 } |
|
| 6088 |
|
| 6089 static void oscar_set_icon(GaimConnection *gc, const char *iconfile) |
|
| 6090 { |
|
| 6091 OscarData *od = gc->proto_data; |
|
| 6092 FILE *file; |
|
| 6093 struct stat st; |
|
| 6094 |
|
| 6095 if (iconfile == NULL) { |
|
| 6096 aim_ssi_delicon(od); |
|
| 6097 } else if (!g_stat(iconfile, &st)) { |
|
| 6098 guchar *buf = g_malloc(st.st_size); |
|
| 6099 file = g_fopen(iconfile, "rb"); |
|
| 6100 if (file) |
|
| 6101 { |
|
| 6102 GaimCipher *cipher; |
|
| 6103 GaimCipherContext *context; |
|
| 6104 guchar md5[16]; |
|
| 6105 int len; |
|
| 6106 |
|
| 6107 /* XXX - Use g_file_get_contents()? */ |
|
| 6108 len = fread(buf, 1, st.st_size, file); |
|
| 6109 fclose(file); |
|
| 6110 |
|
| 6111 cipher = gaim_ciphers_find_cipher("md5"); |
|
| 6112 context = gaim_cipher_context_new(cipher, NULL); |
|
| 6113 gaim_cipher_context_append(context, buf, len); |
|
| 6114 gaim_cipher_context_digest(context, 16, md5, NULL); |
|
| 6115 gaim_cipher_context_destroy(context); |
|
| 6116 |
|
| 6117 aim_ssi_seticon(od, md5, 16); |
|
| 6118 } else |
|
| 6119 gaim_debug_error("oscar", |
|
| 6120 "Can't open buddy icon file!\n"); |
|
| 6121 g_free(buf); |
|
| 6122 } else |
|
| 6123 gaim_debug_error("oscar", "Can't stat buddy icon file!\n"); |
|
| 6124 } |
|
| 6125 |
|
| 6126 /** |
|
| 6127 * Called by the Gaim core to determine whether or not we're |
|
| 6128 * allowed to send a file to this user. |
|
| 6129 */ |
|
| 6130 static gboolean |
|
| 6131 oscar_can_receive_file(GaimConnection *gc, const char *who) |
|
| 6132 { |
|
| 6133 OscarData *od; |
|
| 6134 GaimAccount *account; |
|
| 6135 |
|
| 6136 od = gc->proto_data; |
|
| 6137 account = gaim_connection_get_account(gc); |
|
| 6138 |
|
| 6139 if (od != NULL) |
|
| 6140 { |
|
| 6141 aim_userinfo_t *userinfo; |
|
| 6142 userinfo = aim_locate_finduserinfo(od, who); |
|
| 6143 |
|
| 6144 /* |
|
| 6145 * Don't allowing sending a file to a user that does not support |
|
| 6146 * file transfer, and don't allow sending to ourselves. |
|
| 6147 */ |
|
| 6148 if (((userinfo == NULL) || |
|
| 6149 (userinfo->capabilities & OSCAR_CAPABILITY_SENDFILE)) && |
|
| 6150 aim_sncmp(who, gaim_account_get_username(account))) |
|
| 6151 { |
|
| 6152 return TRUE; |
|
| 6153 } |
|
| 6154 } |
|
| 6155 |
|
| 6156 return FALSE; |
|
| 6157 } |
|
| 6158 |
|
| 6159 static GaimXfer * |
|
| 6160 oscar_new_xfer(GaimConnection *gc, const char *who) |
|
| 6161 { |
|
| 6162 GaimXfer *xfer; |
|
| 6163 OscarData *od; |
|
| 6164 GaimAccount *account; |
|
| 6165 PeerConnection *conn; |
|
| 6166 |
|
| 6167 od = gc->proto_data; |
|
| 6168 account = gaim_connection_get_account(gc); |
|
| 6169 |
|
| 6170 xfer = gaim_xfer_new(account, GAIM_XFER_SEND, who); |
|
| 6171 gaim_xfer_ref(xfer); |
|
| 6172 gaim_xfer_set_init_fnc(xfer, peer_oft_sendcb_init); |
|
| 6173 gaim_xfer_set_cancel_send_fnc(xfer, peer_oft_cb_generic_cancel); |
|
| 6174 gaim_xfer_set_request_denied_fnc(xfer, peer_oft_cb_generic_cancel); |
|
| 6175 gaim_xfer_set_ack_fnc(xfer, peer_oft_sendcb_ack); |
|
| 6176 |
|
| 6177 conn = peer_connection_new(od, OSCAR_CAPABILITY_SENDFILE, who); |
|
| 6178 conn->flags |= PEER_CONNECTION_FLAG_INITIATED_BY_ME; |
|
| 6179 conn->flags |= PEER_CONNECTION_FLAG_APPROVED; |
|
| 6180 aim_icbm_makecookie(conn->cookie); |
|
| 6181 conn->xfer = xfer; |
|
| 6182 xfer->data = conn; |
|
| 6183 |
|
| 6184 return xfer; |
|
| 6185 } |
|
| 6186 |
|
| 6187 /* |
|
| 6188 * Called by the Gaim core when the user indicates that a |
|
| 6189 * file is to be sent to a special someone. |
|
| 6190 */ |
|
| 6191 static void |
|
| 6192 oscar_send_file(GaimConnection *gc, const char *who, const char *file) |
|
| 6193 { |
|
| 6194 GaimXfer *xfer; |
|
| 6195 |
|
| 6196 xfer = oscar_new_xfer(gc, who); |
|
| 6197 |
|
| 6198 if (file != NULL) |
|
| 6199 gaim_xfer_request_accepted(xfer, file); |
|
| 6200 else |
|
| 6201 gaim_xfer_request(xfer); |
|
| 6202 } |
|
| 6203 |
|
| 6204 static GList * |
|
| 6205 oscar_actions(GaimPlugin *plugin, gpointer context) |
|
| 6206 { |
|
| 6207 GaimConnection *gc = (GaimConnection *) context; |
|
| 6208 OscarData *od = gc->proto_data; |
|
| 6209 GList *m = NULL; |
|
| 6210 GaimPluginAction *act; |
|
| 6211 |
|
| 6212 act = gaim_plugin_action_new(_("Set User Info..."), |
|
| 6213 oscar_show_set_info); |
|
| 6214 m = g_list_append(m, act); |
|
| 6215 |
|
| 6216 if (od->icq) |
|
| 6217 { |
|
| 6218 act = gaim_plugin_action_new(_("Set User Info (URL)..."), |
|
| 6219 oscar_show_set_info_icqurl); |
|
| 6220 m = g_list_append(m, act); |
|
| 6221 } |
|
| 6222 |
|
| 6223 act = gaim_plugin_action_new(_("Change Password..."), |
|
| 6224 oscar_change_pass); |
|
| 6225 m = g_list_append(m, act); |
|
| 6226 |
|
| 6227 if (od->authinfo->chpassurl != NULL) |
|
| 6228 { |
|
| 6229 act = gaim_plugin_action_new(_("Change Password (URL)"), |
|
| 6230 oscar_show_chpassurl); |
|
| 6231 m = g_list_append(m, act); |
|
| 6232 |
|
| 6233 act = gaim_plugin_action_new(_("Configure IM Forwarding (URL)"), |
|
| 6234 oscar_show_imforwardingurl); |
|
| 6235 m = g_list_append(m, act); |
|
| 6236 } |
|
| 6237 |
|
| 6238 m = g_list_append(m, NULL); |
|
| 6239 |
|
| 6240 if (od->icq) |
|
| 6241 { |
|
| 6242 /* ICQ actions */ |
|
| 6243 act = gaim_plugin_action_new(_("Set Privacy Options..."), |
|
| 6244 oscar_show_icq_privacy_opts); |
|
| 6245 m = g_list_append(m, act); |
|
| 6246 } |
|
| 6247 else |
|
| 6248 { |
|
| 6249 /* AIM actions */ |
|
| 6250 act = gaim_plugin_action_new(_("Format Screen Name..."), |
|
| 6251 oscar_show_format_screenname); |
|
| 6252 m = g_list_append(m, act); |
|
| 6253 |
|
| 6254 act = gaim_plugin_action_new(_("Confirm Account"), |
|
| 6255 oscar_confirm_account); |
|
| 6256 m = g_list_append(m, act); |
|
| 6257 |
|
| 6258 act = gaim_plugin_action_new(_("Display Currently Registered E-Mail Address"), |
|
| 6259 oscar_show_email); |
|
| 6260 m = g_list_append(m, act); |
|
| 6261 |
|
| 6262 act = gaim_plugin_action_new(_("Change Currently Registered E-Mail Address..."), |
|
| 6263 oscar_show_change_email); |
|
| 6264 m = g_list_append(m, act); |
|
| 6265 } |
|
| 6266 |
|
| 6267 m = g_list_append(m, NULL); |
|
| 6268 |
|
| 6269 act = gaim_plugin_action_new(_("Show Buddies Awaiting Authorization"), |
|
| 6270 oscar_show_awaitingauth); |
|
| 6271 m = g_list_append(m, act); |
|
| 6272 |
|
| 6273 m = g_list_append(m, NULL); |
|
| 6274 |
|
| 6275 act = gaim_plugin_action_new(_("Search for Buddy by E-Mail Address..."), |
|
| 6276 oscar_show_find_email); |
|
| 6277 m = g_list_append(m, act); |
|
| 6278 |
|
| 6279 #if 0 |
|
| 6280 act = gaim_plugin_action_new(_("Search for Buddy by Information"), |
|
| 6281 show_find_info); |
|
| 6282 m = g_list_append(m, act); |
|
| 6283 #endif |
|
| 6284 |
|
| 6285 return m; |
|
| 6286 } |
|
| 6287 |
|
| 6288 static void oscar_change_passwd(GaimConnection *gc, const char *old, const char *new) |
|
| 6289 { |
|
| 6290 OscarData *od = gc->proto_data; |
|
| 6291 |
|
| 6292 if (od->icq) { |
|
| 6293 aim_icq_changepasswd(od, new); |
|
| 6294 } else { |
|
| 6295 FlapConnection *conn; |
|
| 6296 conn = flap_connection_getbytype(od, SNAC_FAMILY_ADMIN); |
|
| 6297 if (conn) { |
|
| 6298 aim_admin_changepasswd(od, conn, new, old); |
|
| 6299 } else { |
|
| 6300 od->chpass = TRUE; |
|
| 6301 od->oldp = g_strdup(old); |
|
| 6302 od->newp = g_strdup(new); |
|
| 6303 aim_reqservice(od, SNAC_FAMILY_ADMIN); |
|
| 6304 } |
|
| 6305 } |
|
| 6306 } |
|
| 6307 |
|
| 6308 static void |
|
| 6309 oscar_convo_closed(GaimConnection *gc, const char *who) |
|
| 6310 { |
|
| 6311 OscarData *od; |
|
| 6312 PeerConnection *conn; |
|
| 6313 |
|
| 6314 od = gc->proto_data; |
|
| 6315 conn = peer_connection_find_by_type(od, who, OSCAR_CAPABILITY_DIRECTIM); |
|
| 6316 |
|
| 6317 if (conn != NULL) |
|
| 6318 { |
|
| 6319 if (!conn->ready) |
|
| 6320 aim_im_sendch2_cancel(conn); |
|
| 6321 |
|
| 6322 peer_connection_destroy(conn, OSCAR_DISCONNECT_LOCAL_CLOSED); |
|
| 6323 } |
|
| 6324 } |
|
| 6325 |
|
| 6326 static void |
|
| 6327 recent_buddies_cb(const char *name, GaimPrefType type, |
|
| 6328 gconstpointer value, gpointer data) |
|
| 6329 { |
|
| 6330 GaimConnection *gc = data; |
|
| 6331 OscarData *od = gc->proto_data; |
|
| 6332 guint32 presence; |
|
| 6333 |
|
| 6334 presence = aim_ssi_getpresence(od->ssi.local); |
|
| 6335 |
|
| 6336 if (value) { |
|
| 6337 presence &= ~AIM_SSI_PRESENCE_FLAG_NORECENTBUDDIES; |
|
| 6338 aim_ssi_setpresence(od, presence); |
|
| 6339 } else { |
|
| 6340 presence |= AIM_SSI_PRESENCE_FLAG_NORECENTBUDDIES; |
|
| 6341 aim_ssi_setpresence(od, presence); |
|
| 6342 } |
|
| 6343 } |
|
| 6344 |
|
| 6345 #ifdef USE_PRPL_PREFERENCES |
|
| 6346 ppref = gaim_plugin_pref_new_with_name_and_label("/plugins/prpl/oscar/recent_buddies", _("Use recent buddies group")); |
|
| 6347 gaim_plugin_pref_frame_add(frame, ppref); |
|
| 6348 |
|
| 6349 ppref = gaim_plugin_pref_new_with_name_and_label("/plugins/prpl/oscar/show_idle", _("Show how long you have been idle")); |
|
| 6350 gaim_plugin_pref_frame_add(frame, ppref); |
|
| 6351 #endif |
|
| 6352 |
|
| 6353 static const char * |
|
| 6354 oscar_normalize(const GaimAccount *account, const char *str) |
|
| 6355 { |
|
| 6356 static char buf[BUF_LEN]; |
|
| 6357 char *tmp1, *tmp2; |
|
| 6358 int i, j; |
|
| 6359 |
|
| 6360 g_return_val_if_fail(str != NULL, NULL); |
|
| 6361 |
|
| 6362 strncpy(buf, str, BUF_LEN); |
|
| 6363 for (i=0, j=0; buf[j]; i++, j++) |
|
| 6364 { |
|
| 6365 while (buf[j] == ' ') |
|
| 6366 j++; |
|
| 6367 buf[i] = buf[j]; |
|
| 6368 } |
|
| 6369 buf[i] = '\0'; |
|
| 6370 |
|
| 6371 tmp1 = g_utf8_strdown(buf, -1); |
|
| 6372 tmp2 = g_utf8_normalize(tmp1, -1, G_NORMALIZE_DEFAULT); |
|
| 6373 g_snprintf(buf, sizeof(buf), "%s", tmp2); |
|
| 6374 g_free(tmp2); |
|
| 6375 g_free(tmp1); |
|
| 6376 |
|
| 6377 return buf; |
|
| 6378 } |
|
| 6379 |
|
| 6380 static gboolean |
|
| 6381 oscar_offline_message(const GaimBuddy *buddy) |
|
| 6382 { |
|
| 6383 OscarData *od; |
|
| 6384 GaimAccount *account; |
|
| 6385 GaimConnection *gc; |
|
| 6386 |
|
| 6387 account = gaim_buddy_get_account(buddy); |
|
| 6388 gc = gaim_account_get_connection(account); |
|
| 6389 od = (OscarData *)gc->proto_data; |
|
| 6390 |
|
| 6391 return (od->icq && aim_sn_is_icq(gaim_account_get_username(account))); |
|
| 6392 } |
|
| 6393 |
|
| 6394 static GaimPluginProtocolInfo prpl_info = |
|
| 6395 { |
|
| 6396 OPT_PROTO_MAIL_CHECK | OPT_PROTO_IM_IMAGE, |
|
| 6397 NULL, /* user_splits */ |
|
| 6398 NULL, /* protocol_options */ |
|
| 6399 {"jpeg,gif,bmp,ico", 48, 48, 50, 50, |
|
| 6400 GAIM_ICON_SCALE_SEND | GAIM_ICON_SCALE_DISPLAY}, /* icon_spec */ |
|
| 6401 oscar_list_icon, /* list_icon */ |
|
| 6402 oscar_list_emblems, /* list_emblems */ |
|
| 6403 oscar_status_text, /* status_text */ |
|
| 6404 oscar_tooltip_text, /* tooltip_text */ |
|
| 6405 oscar_status_types, /* status_types */ |
|
| 6406 oscar_blist_node_menu, /* blist_node_menu */ |
|
| 6407 oscar_chat_info, /* chat_info */ |
|
| 6408 oscar_chat_info_defaults, /* chat_info_defaults */ |
|
| 6409 oscar_login, /* login */ |
|
| 6410 oscar_close, /* close */ |
|
| 6411 oscar_send_im, /* send_im */ |
|
| 6412 oscar_set_info, /* set_info */ |
|
| 6413 oscar_send_typing, /* send_typing */ |
|
| 6414 oscar_get_info, /* get_info */ |
|
| 6415 oscar_set_status, /* set_status */ |
|
| 6416 oscar_set_idle, /* set_idle */ |
|
| 6417 oscar_change_passwd, /* change_passwd */ |
|
| 6418 oscar_add_buddy, /* add_buddy */ |
|
| 6419 NULL, /* add_buddies */ |
|
| 6420 oscar_remove_buddy, /* remove_buddy */ |
|
| 6421 NULL, /* remove_buddies */ |
|
| 6422 oscar_add_permit, /* add_permit */ |
|
| 6423 oscar_add_deny, /* add_deny */ |
|
| 6424 oscar_rem_permit, /* rem_permit */ |
|
| 6425 oscar_rem_deny, /* rem_deny */ |
|
| 6426 oscar_set_permit_deny, /* set_permit_deny */ |
|
| 6427 oscar_join_chat, /* join_chat */ |
|
| 6428 NULL, /* reject_chat */ |
|
| 6429 oscar_get_chat_name, /* get_chat_name */ |
|
| 6430 oscar_chat_invite, /* chat_invite */ |
|
| 6431 oscar_chat_leave, /* chat_leave */ |
|
| 6432 NULL, /* chat_whisper */ |
|
| 6433 oscar_send_chat, /* chat_send */ |
|
| 6434 oscar_keepalive, /* keepalive */ |
|
| 6435 NULL, /* register_user */ |
|
| 6436 NULL, /* get_cb_info */ |
|
| 6437 NULL, /* get_cb_away */ |
|
| 6438 oscar_alias_buddy, /* alias_buddy */ |
|
| 6439 oscar_move_buddy, /* group_buddy */ |
|
| 6440 oscar_rename_group, /* rename_group */ |
|
| 6441 NULL, /* buddy_free */ |
|
| 6442 oscar_convo_closed, /* convo_closed */ |
|
| 6443 oscar_normalize, /* normalize */ |
|
| 6444 oscar_set_icon, /* set_buddy_icon */ |
|
| 6445 NULL, /* remove_group */ |
|
| 6446 NULL, /* get_cb_real_name */ |
|
| 6447 NULL, /* set_chat_topic */ |
|
| 6448 NULL, /* find_blist_chat */ |
|
| 6449 NULL, /* roomlist_get_list */ |
|
| 6450 NULL, /* roomlist_cancel */ |
|
| 6451 NULL, /* roomlist_expand_category */ |
|
| 6452 oscar_can_receive_file, /* can_receive_file */ |
|
| 6453 oscar_send_file, /* send_file */ |
|
| 6454 oscar_new_xfer, /* new_xfer */ |
|
| 6455 oscar_offline_message, /* offline_message */ |
|
| 6456 NULL, /* whiteboard_prpl_ops */ |
|
| 6457 }; |
|
| 6458 |
|
| 6459 static GaimPluginInfo info = |
|
| 6460 { |
|
| 6461 GAIM_PLUGIN_MAGIC, |
|
| 6462 GAIM_MAJOR_VERSION, |
|
| 6463 GAIM_MINOR_VERSION, |
|
| 6464 GAIM_PLUGIN_PROTOCOL, /**< type */ |
|
| 6465 NULL, /**< ui_requirement */ |
|
| 6466 0, /**< flags */ |
|
| 6467 NULL, /**< dependencies */ |
|
| 6468 GAIM_PRIORITY_DEFAULT, /**< priority */ |
|
| 6469 |
|
| 6470 "prpl-oscar", /**< id */ |
|
| 6471 "AIM/ICQ", /**< name */ |
|
| 6472 VERSION, /**< version */ |
|
| 6473 /** summary */ |
|
| 6474 N_("AIM/ICQ Protocol Plugin"), |
|
| 6475 /** description */ |
|
| 6476 N_("AIM/ICQ Protocol Plugin"), |
|
| 6477 NULL, /**< author */ |
|
| 6478 GAIM_WEBSITE, /**< homepage */ |
|
| 6479 |
|
| 6480 NULL, /**< load */ |
|
| 6481 NULL, /**< unload */ |
|
| 6482 NULL, /**< destroy */ |
|
| 6483 |
|
| 6484 NULL, /**< ui_info */ |
|
| 6485 &prpl_info, /**< extra_info */ |
|
| 6486 NULL, |
|
| 6487 oscar_actions |
|
| 6488 }; |
|
| 6489 |
|
| 6490 static void |
|
| 6491 init_plugin(GaimPlugin *plugin) |
|
| 6492 { |
|
| 6493 GaimAccountOption *option; |
|
| 6494 |
|
| 6495 option = gaim_account_option_string_new(_("Server"), "server", OSCAR_DEFAULT_LOGIN_SERVER); |
|
| 6496 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
|
| 6497 |
|
| 6498 option = gaim_account_option_int_new(_("Port"), "port", OSCAR_DEFAULT_LOGIN_PORT); |
|
| 6499 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
|
| 6500 |
|
| 6501 option = gaim_account_option_string_new(_("Encoding"), "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING); |
|
| 6502 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
|
| 6503 |
|
| 6504 option = gaim_account_option_bool_new( |
|
| 6505 _("Always use AIM/ICQ proxy server\n(slower, but does not reveal your IP address)"), "always_use_rv_proxy", |
|
| 6506 OSCAR_DEFAULT_ALWAYS_USE_RV_PROXY); |
|
| 6507 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); |
|
| 6508 |
|
| 6509 /* Preferences */ |
|
| 6510 gaim_prefs_add_none("/plugins/prpl/oscar"); |
|
| 6511 gaim_prefs_add_bool("/plugins/prpl/oscar/recent_buddies", FALSE); |
|
| 6512 gaim_prefs_add_bool("/plugins/prpl/oscar/show_idle", FALSE); |
|
| 6513 gaim_prefs_remove("/plugins/prpl/oscar/always_use_rv_proxy"); |
|
| 6514 } |
|
| 6515 |
|
| 6516 GAIM_INIT_PLUGIN(oscar, init_plugin, info); |
|