Mercurial > pidgin.yaz
comparison src/protocols/oscar/oscar.c @ 5129:c19cc54f4df6
[gaim-migrate @ 5492]
Stuff I did (in order from most important to least):
-Made set away message and set profile count the number of bytes
rather than the number of characters. This fixes the lack of a
warning dialog when setting info that needs an encoding other than
ascii or iso8859-1. (Because "hi" in UCS-2BE is 4 bytes but "hi"
in utf8 is only 2.)
-Created an oscar_encoding_to_utf8 function to convert from a given
encoding to utf8. This is AIM/ICQ specific.
-Added a "Profile:" and "Away Message:" line to the get info response
window. Is it better this way or without it? I thought it would be
good if there was a way for users to tell which text was the away
message and which was the info, but I also think this solution could
be nicer looking.
-Added a little check for some server icon stuff because someone
reported an obscure crash.
-Shuffled some stuff around in oscar.c
-Bouldered on the little wall outside of the gym today. It's much
more difficult than climbing inside. I think my forearms are just
a bit too weak. The holds are tiny, though.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Mon, 14 Apr 2003 04:52:42 +0000 |
parents | 74139d2562f5 |
children | feda37d46e17 |
comparison
equal
deleted
inserted
replaced
5128:29a834316b34 | 5129:c19cc54f4df6 |
---|---|
197 struct gaim_connection *gc; | 197 struct gaim_connection *gc; |
198 gchar *name; | 198 gchar *name; |
199 gchar *nick; | 199 gchar *nick; |
200 }; | 200 }; |
201 | 201 |
202 static void gaim_free_name_data(struct name_data *data) { | 202 static char *msgerrreason[] = { |
203 g_free(data->name); | 203 N_("Invalid error"), |
204 g_free(data->nick); | 204 N_("Invalid SNAC"), |
205 g_free(data); | 205 N_("Rate to host"), |
206 } | 206 N_("Rate to client"), |
207 | 207 N_("Not logged in"), |
208 static struct direct_im *find_direct_im(struct oscar_data *od, const char *who) { | 208 N_("Service unavailable"), |
209 GSList *d = od->direct_ims; | 209 N_("Service not defined"), |
210 struct direct_im *m = NULL; | 210 N_("Obsolete SNAC"), |
211 | 211 N_("Not supported by host"), |
212 while (d) { | 212 N_("Not supported by client"), |
213 m = (struct direct_im *)d->data; | 213 N_("Refused by client"), |
214 if (!aim_sncmp(who, m->name)) | 214 N_("Reply too big"), |
215 return m; | 215 N_("Responses lost"), |
216 d = d->next; | 216 N_("Request denied"), |
217 } | 217 N_("Busted SNAC payload"), |
218 | 218 N_("Insufficient rights"), |
219 return NULL; | 219 N_("In local permit/deny"), |
220 } | 220 N_("Too evil (sender)"), |
221 | 221 N_("Too evil (receiver)"), |
222 static char *extract_name(const char *name) { | 222 N_("User temporarily unavailable"), |
223 char *tmp, *x; | 223 N_("No match"), |
224 int i, j; | 224 N_("List overflow"), |
225 | 225 N_("Request ambiguous"), |
226 if (!name) | 226 N_("Queue full"), |
227 return NULL; | 227 N_("Not while on AOL") |
228 | 228 }; |
229 x = strchr(name, '-'); | 229 static int msgerrreasonlen = 25; |
230 | |
231 if (!x) return NULL; | |
232 x = strchr(++x, '-'); | |
233 if (!x) return NULL; | |
234 tmp = g_strdup(++x); | |
235 | |
236 for (i = 0, j = 0; x[i]; i++) { | |
237 char hex[3]; | |
238 if (x[i] != '%') { | |
239 tmp[j++] = x[i]; | |
240 continue; | |
241 } | |
242 strncpy(hex, x + ++i, 2); hex[2] = 0; | |
243 i++; | |
244 tmp[j++] = strtol(hex, NULL, 16); | |
245 } | |
246 | |
247 tmp[j] = 0; | |
248 return tmp; | |
249 } | |
250 | |
251 static struct chat_connection *find_oscar_chat(struct gaim_connection *gc, int id) { | |
252 GSList *g = ((struct oscar_data *)gc->proto_data)->oscar_chats; | |
253 struct chat_connection *c = NULL; | |
254 | |
255 while (g) { | |
256 c = (struct chat_connection *)g->data; | |
257 if (c->id == id) | |
258 break; | |
259 g = g->next; | |
260 c = NULL; | |
261 } | |
262 | |
263 return c; | |
264 } | |
265 | |
266 static struct chat_connection *find_oscar_chat_by_conn(struct gaim_connection *gc, | |
267 aim_conn_t *conn) { | |
268 GSList *g = ((struct oscar_data *)gc->proto_data)->oscar_chats; | |
269 struct chat_connection *c = NULL; | |
270 | |
271 while (g) { | |
272 c = (struct chat_connection *)g->data; | |
273 if (c->conn == conn) | |
274 break; | |
275 g = g->next; | |
276 c = NULL; | |
277 } | |
278 | |
279 return c; | |
280 } | |
281 | 230 |
282 /* All the libfaim->gaim callback functions */ | 231 /* All the libfaim->gaim callback functions */ |
283 static int gaim_parse_auth_resp (aim_session_t *, aim_frame_t *, ...); | 232 static int gaim_parse_auth_resp (aim_session_t *, aim_frame_t *, ...); |
284 static int gaim_parse_login (aim_session_t *, aim_frame_t *, ...); | 233 static int gaim_parse_login (aim_session_t *, aim_frame_t *, ...); |
285 static int gaim_handle_redirect (aim_session_t *, aim_frame_t *, ...); | 234 static int gaim_handle_redirect (aim_session_t *, aim_frame_t *, ...); |
351 static int oscar_sendfile_done (aim_session_t *, aim_frame_t *, ...); | 300 static int oscar_sendfile_done (aim_session_t *, aim_frame_t *, ...); |
352 | 301 |
353 /* for icons */ | 302 /* for icons */ |
354 static gboolean gaim_icon_timerfunc(gpointer data); | 303 static gboolean gaim_icon_timerfunc(gpointer data); |
355 | 304 |
356 static fu32_t check_encoding(const char *utf8); | 305 static void gaim_free_name_data(struct name_data *data) { |
357 static fu32_t parse_encoding(const char *enc); | 306 g_free(data->name); |
358 | 307 g_free(data->nick); |
359 static char *msgerrreason[] = { | 308 g_free(data); |
360 N_("Invalid error"), | 309 } |
361 N_("Invalid SNAC"), | 310 |
362 N_("Rate to host"), | 311 static fu32_t oscar_encoding_check(const char *utf8) |
363 N_("Rate to client"), | 312 { |
364 N_("Not logged in"), | 313 int i = 0; |
365 N_("Service unavailable"), | 314 fu32_t encodingflag = 0; |
366 N_("Service not defined"), | 315 |
367 N_("Obsolete SNAC"), | 316 /* Determine how we can send this message. Per the warnings elsewhere |
368 N_("Not supported by host"), | 317 * in this file, these little checks determine the simplest encoding |
369 N_("Not supported by client"), | 318 * we can use for a given message send using it. */ |
370 N_("Refused by client"), | 319 while (utf8[i]) { |
371 N_("Reply too big"), | 320 if ((unsigned char)utf8[i] > 0x7f) { |
372 N_("Responses lost"), | 321 /* not ASCII! */ |
373 N_("Request denied"), | 322 encodingflag = AIM_IMFLAGS_ISO_8859_1; |
374 N_("Busted SNAC payload"), | 323 break; |
375 N_("Insufficient rights"), | 324 } |
376 N_("In local permit/deny"), | 325 i++; |
377 N_("Too evil (sender)"), | 326 } |
378 N_("Too evil (receiver)"), | 327 while (utf8[i]) { |
379 N_("User temporarily unavailable"), | 328 /* ISO-8859-1 is 0x00-0xbf in the first byte |
380 N_("No match"), | 329 * followed by 0xc0-0xc3 in the second */ |
381 N_("List overflow"), | 330 if ((unsigned char)utf8[i] < 0x80) { |
382 N_("Request ambiguous"), | 331 i++; |
383 N_("Queue full"), | 332 continue; |
384 N_("Not while on AOL") | 333 } else if (((unsigned char)utf8[i] & 0xfc) == 0xc0 && |
385 }; | 334 ((unsigned char)utf8[i + 1] & 0xc0) == 0x80) { |
386 static int msgerrreasonlen = 25; | 335 i += 2; |
336 continue; | |
337 } | |
338 encodingflag = AIM_IMFLAGS_UNICODE; | |
339 break; | |
340 } | |
341 | |
342 return encodingflag; | |
343 } | |
344 | |
345 static fu32_t oscar_encoding_parse(const char *enc) | |
346 { | |
347 char *charset; | |
348 | |
349 /* If anything goes wrong, fall back on ASCII and print a message */ | |
350 if (enc == NULL) { | |
351 debug_printf("Encoding was null, that's odd\n"); | |
352 return 0; | |
353 } | |
354 charset = strstr(enc, "charset="); | |
355 if (charset == NULL) { | |
356 debug_printf("No charset specified for info, assuming ASCII\n"); | |
357 return 0; | |
358 } | |
359 charset += 8; | |
360 if (!strcmp(charset, "\"us-ascii\"") || !strcmp(charset, "\"utf-8\"")) { | |
361 /* UTF-8 is our native charset, ASCII is a proper subset */ | |
362 return 0; | |
363 } else if (!strcmp(charset, "\"iso-8859-1\"")) { | |
364 return AIM_IMFLAGS_ISO_8859_1; | |
365 } else if (!strcmp(charset, "\"unicode-2-0\"")) { | |
366 return AIM_IMFLAGS_UNICODE; | |
367 } else { | |
368 debug_printf("Unrecognized character set '%s', using ASCII\n", charset); | |
369 return 0; | |
370 } | |
371 } | |
372 | |
373 gchar *oscar_encoding_to_utf8(const char *encoding, char *text, int textlen) | |
374 { | |
375 gchar *utf8 = NULL; | |
376 int flags = oscar_encoding_parse(encoding); | |
377 | |
378 switch (flags) { | |
379 case 0: | |
380 utf8 = g_strndup(text, textlen); | |
381 break; | |
382 case AIM_IMFLAGS_ISO_8859_1: | |
383 utf8 = g_convert(text, textlen, "UTF-8", "ISO-8859-1", NULL, NULL, NULL); | |
384 break; | |
385 case AIM_IMFLAGS_UNICODE: | |
386 utf8 = g_convert(text, textlen, "UTF-8", "UCS-2BE", NULL, NULL, NULL); | |
387 break; | |
388 } | |
389 | |
390 return utf8; | |
391 } | |
392 | |
393 static struct direct_im *find_direct_im(struct oscar_data *od, const char *who) { | |
394 GSList *d = od->direct_ims; | |
395 struct direct_im *m = NULL; | |
396 | |
397 while (d) { | |
398 m = (struct direct_im *)d->data; | |
399 if (!aim_sncmp(who, m->name)) | |
400 return m; | |
401 d = d->next; | |
402 } | |
403 | |
404 return NULL; | |
405 } | |
406 | |
407 static char *extract_name(const char *name) { | |
408 char *tmp, *x; | |
409 int i, j; | |
410 | |
411 if (!name) | |
412 return NULL; | |
413 | |
414 x = strchr(name, '-'); | |
415 | |
416 if (!x) return NULL; | |
417 x = strchr(++x, '-'); | |
418 if (!x) return NULL; | |
419 tmp = g_strdup(++x); | |
420 | |
421 for (i = 0, j = 0; x[i]; i++) { | |
422 char hex[3]; | |
423 if (x[i] != '%') { | |
424 tmp[j++] = x[i]; | |
425 continue; | |
426 } | |
427 strncpy(hex, x + ++i, 2); hex[2] = 0; | |
428 i++; | |
429 tmp[j++] = strtol(hex, NULL, 16); | |
430 } | |
431 | |
432 tmp[j] = 0; | |
433 return tmp; | |
434 } | |
435 | |
436 static struct chat_connection *find_oscar_chat(struct gaim_connection *gc, int id) { | |
437 GSList *g = ((struct oscar_data *)gc->proto_data)->oscar_chats; | |
438 struct chat_connection *c = NULL; | |
439 | |
440 while (g) { | |
441 c = (struct chat_connection *)g->data; | |
442 if (c->id == id) | |
443 break; | |
444 g = g->next; | |
445 c = NULL; | |
446 } | |
447 | |
448 return c; | |
449 } | |
450 | |
451 static struct chat_connection *find_oscar_chat_by_conn(struct gaim_connection *gc, | |
452 aim_conn_t *conn) { | |
453 GSList *g = ((struct oscar_data *)gc->proto_data)->oscar_chats; | |
454 struct chat_connection *c = NULL; | |
455 | |
456 while (g) { | |
457 c = (struct chat_connection *)g->data; | |
458 if (c->conn == conn) | |
459 break; | |
460 g = g->next; | |
461 c = NULL; | |
462 } | |
463 | |
464 return c; | |
465 } | |
387 | 466 |
388 static void gaim_odc_disconnect(aim_session_t *sess, aim_conn_t *conn) { | 467 static void gaim_odc_disconnect(aim_session_t *sess, aim_conn_t *conn) { |
389 struct gaim_connection *gc = sess->aux_data; | 468 struct gaim_connection *gc = sess->aux_data; |
390 struct oscar_data *od = (struct oscar_data *)gc->proto_data; | 469 struct oscar_data *od = (struct oscar_data *)gc->proto_data; |
391 struct gaim_conversation *cnv; | 470 struct gaim_conversation *cnv; |
3044 struct oscar_data *od = gc->proto_data; | 3123 struct oscar_data *od = gc->proto_data; |
3045 char header[BUF_LONG]; | 3124 char header[BUF_LONG]; |
3046 GSList *l = od->evilhack; | 3125 GSList *l = od->evilhack; |
3047 gboolean evilhack = FALSE; | 3126 gboolean evilhack = FALSE; |
3048 gchar *membersince = NULL, *onlinesince = NULL, *idle = NULL; | 3127 gchar *membersince = NULL, *onlinesince = NULL, *idle = NULL; |
3049 fu32_t flags; | |
3050 va_list ap; | 3128 va_list ap; |
3051 aim_userinfo_t *info; | 3129 aim_userinfo_t *info; |
3052 fu16_t infotype; | 3130 fu16_t infotype; |
3053 char *text_enc = NULL, *text = NULL, *utf8 = NULL; | 3131 char *text_enc = NULL, *text = NULL, *utf8 = NULL; |
3054 int text_len; | 3132 int text_len; |
3060 text = va_arg(ap, char *); | 3138 text = va_arg(ap, char *); |
3061 text_len = va_arg(ap, int); | 3139 text_len = va_arg(ap, int); |
3062 va_end(ap); | 3140 va_end(ap); |
3063 | 3141 |
3064 if (text_len > 0) { | 3142 if (text_len > 0) { |
3065 flags = parse_encoding (text_enc); | 3143 if (!(utf8 = oscar_encoding_to_utf8(text_enc, text, text_len))) { |
3066 switch (flags) { | |
3067 case 0: | |
3068 utf8 = g_strndup(text, text_len); | |
3069 break; | |
3070 case AIM_IMFLAGS_ISO_8859_1: | |
3071 utf8 = g_convert(text, text_len, "UTF-8", "ISO-8859-1", NULL, NULL, NULL); | |
3072 break; | |
3073 case AIM_IMFLAGS_UNICODE: | |
3074 utf8 = g_convert(text, text_len, "UTF-8", "UCS-2BE", NULL, NULL, NULL); | |
3075 break; | |
3076 default: | |
3077 utf8 = g_strdup(_("<i>Unable to display information because it was sent in an unknown encoding.</i>")); | 3144 utf8 = g_strdup(_("<i>Unable to display information because it was sent in an unknown encoding.</i>")); |
3078 debug_printf("Encountered an unknown encoding while parsing userinfo\n"); | 3145 debug_printf("Encountered an unknown encoding while parsing userinfo\n"); |
3079 } | 3146 } |
3080 } | 3147 } |
3081 | 3148 |
3131 (utf8 && *utf8) ? away_subs(utf8, gc->username) : | 3198 (utf8 && *utf8) ? away_subs(utf8, gc->username) : |
3132 _("<i>User has no away message</i>"), NULL); | 3199 _("<i>User has no away message</i>"), NULL); |
3133 } else { | 3200 } else { |
3134 g_show_info_text(gc, info->sn, 0, | 3201 g_show_info_text(gc, info->sn, 0, |
3135 header, | 3202 header, |
3203 (utf8 && *utf8) ? _("<b>Away Message:</b><br>") : NULL, | |
3136 (utf8 && *utf8) ? away_subs(utf8, gc->username) : NULL, | 3204 (utf8 && *utf8) ? away_subs(utf8, gc->username) : NULL, |
3137 (utf8 && *utf8) ? "<hr>" : NULL, | 3205 (utf8 && *utf8) ? "<hr>" : NULL, |
3138 NULL); | 3206 NULL); |
3139 } | 3207 } |
3140 } else if (infotype == AIM_GETINFO_CAPABILITIES) { | 3208 } else if (infotype == AIM_GETINFO_CAPABILITIES) { |
3144 caps_string(info->capabilities), | 3212 caps_string(info->capabilities), |
3145 "</i>", | 3213 "</i>", |
3146 NULL); | 3214 NULL); |
3147 } else { | 3215 } else { |
3148 g_show_info_text(gc, info->sn, 1, | 3216 g_show_info_text(gc, info->sn, 1, |
3149 (utf8 && *utf8) ? away_subs(utf8, gc->username) : | 3217 (utf8 && *utf8) ? _("<b>Profile:</b><br>") : _("<i>No Information Provided</i>"), |
3150 _("<i>No Information Provided</i>"), | 3218 (utf8 && *utf8) ? away_subs(utf8, gc->username) : NULL, |
3151 NULL); | 3219 NULL); |
3152 } | 3220 } |
3153 | 3221 |
3154 g_free(utf8); | 3222 g_free(utf8); |
3155 | 3223 |
3398 iconlen = va_arg(ap, int); | 3466 iconlen = va_arg(ap, int); |
3399 va_end(ap); | 3467 va_end(ap); |
3400 | 3468 |
3401 if (iconlen > 0) { | 3469 if (iconlen > 0) { |
3402 char *b16; | 3470 char *b16; |
3403 struct buddy *b; | 3471 struct buddy *b = gaim_find_buddy(gc->account, sn); |
3404 set_icon_data(gc, sn, icon, iconlen); | 3472 set_icon_data(gc, sn, icon, iconlen); |
3405 b16 = tobase16(iconcsum, iconcsumlen); | 3473 b16 = tobase16(iconcsum, iconcsumlen); |
3406 b = gaim_find_buddy(gc->account, sn); | 3474 if (b16) { |
3407 gaim_buddy_set_setting(b, "icon_checksum", b16); | 3475 gaim_buddy_set_setting(b, "icon_checksum", b16); |
3408 gaim_blist_save(); | 3476 gaim_blist_save(); |
3409 if(b16) | |
3410 free(b16); | 3477 free(b16); |
3478 } | |
3411 } | 3479 } |
3412 | 3480 |
3413 cur = od->requesticon; | 3481 cur = od->requesticon; |
3414 while (cur) { | 3482 while (cur) { |
3415 char *cursn = cur->data; | 3483 char *cursn = cur->data; |
3697 od->rights.maxsiglen = od->rights.maxawaymsglen = (guint)maxsiglen; | 3765 od->rights.maxsiglen = od->rights.maxawaymsglen = (guint)maxsiglen; |
3698 | 3766 |
3699 if (od->icq) | 3767 if (od->icq) |
3700 aim_bos_setprofile(sess, fr->conn, NULL, NULL, 0, NULL, NULL, 0, caps_icq); | 3768 aim_bos_setprofile(sess, fr->conn, NULL, NULL, 0, NULL, NULL, 0, caps_icq); |
3701 else { | 3769 else { |
3702 flags = check_encoding (gc->account->user_info); | 3770 flags = oscar_encoding_check (gc->account->user_info); |
3703 | 3771 |
3704 if (flags == 0) { | 3772 if (flags == 0) { |
3705 aim_bos_setprofile(sess, fr->conn, "us-ascii", gc->account->user_info, | 3773 aim_bos_setprofile(sess, fr->conn, "us-ascii", gc->account->user_info, |
3706 strlen(gc->account->user_info), NULL, NULL, 0, caps_aim); | 3774 strlen(gc->account->user_info), NULL, NULL, 0, caps_aim); |
3707 } else { | 3775 } else { |
4195 } | 4263 } |
4196 | 4264 |
4197 args.destsn = name; | 4265 args.destsn = name; |
4198 | 4266 |
4199 len = strlen(message); | 4267 len = strlen(message); |
4200 args.flags |= check_encoding(message); | 4268 args.flags |= oscar_encoding_check(message); |
4201 if (args.flags & AIM_IMFLAGS_UNICODE) { | 4269 if (args.flags & AIM_IMFLAGS_UNICODE) { |
4202 debug_printf("Sending Unicode IM\n"); | 4270 debug_printf("Sending Unicode IM\n"); |
4203 args.charset = 0x0002; | 4271 args.charset = 0x0002; |
4204 args.charsubset = 0x0000; | 4272 args.charsubset = 0x0000; |
4205 args.msg = g_convert(message, len, "UCS-2BE", "UTF-8", NULL, &len, &err); | 4273 args.msg = g_convert(message, len, "UCS-2BE", "UTF-8", NULL, &len, &err); |
4275 aim_setdirectoryinfo(od->sess, od->conn, first, middle, last, | 4343 aim_setdirectoryinfo(od->sess, od->conn, first, middle, last, |
4276 maiden, NULL, NULL, city, state, NULL, 0, web); | 4344 maiden, NULL, NULL, city, state, NULL, 0, web); |
4277 } | 4345 } |
4278 | 4346 |
4279 | 4347 |
4280 static void oscar_set_idle(struct gaim_connection *g, int time) { | 4348 static void oscar_set_idle(struct gaim_connection *gc, int time) { |
4281 struct oscar_data *od = (struct oscar_data *)g->proto_data; | 4349 struct oscar_data *od = (struct oscar_data *)gc->proto_data; |
4282 aim_bos_setidle(od->sess, od->conn, time); | 4350 aim_bos_setidle(od->sess, od->conn, time); |
4283 } | 4351 } |
4284 | 4352 |
4285 static void oscar_set_info(struct gaim_connection *g, char *info) { | 4353 static void oscar_set_info(struct gaim_connection *gc, char *text) { |
4286 struct oscar_data *od = (struct oscar_data *)g->proto_data; | 4354 struct oscar_data *od = (struct oscar_data *)gc->proto_data; |
4287 gchar *inforeal, *unicode; | 4355 fu32_t flags = 0; |
4288 fu32_t flags; | 4356 char *msg = NULL; |
4289 int unicode_len; | 4357 int msglen = 0; |
4290 | 4358 |
4291 if (od->rights.maxsiglen == 0) | 4359 if (od->rights.maxsiglen == 0) |
4292 do_error_dialog(_("Unable to set AIM profile."), | 4360 do_error_dialog(_("Unable to set AIM profile."), |
4293 _("You have probably requested to set your profile before the login procedure completed. " | 4361 _("You have probably requested to set your profile before the login procedure completed. " |
4294 "Your profile remains unset; try setting it again when you are fully connected."), GAIM_ERROR); | 4362 "Your profile remains unset; try setting it again when you are fully connected."), GAIM_WARNING); |
4295 | |
4296 if (strlen(info) > od->rights.maxsiglen) { | |
4297 gchar *errstr; | |
4298 | |
4299 errstr = g_strdup_printf(_("The maximum profile length of %d bytes has been exceeded. " | |
4300 "Gaim has truncated and set it."), od->rights.maxsiglen); | |
4301 do_error_dialog("Profile too long.", errstr, GAIM_WARNING); | |
4302 | |
4303 g_free(errstr); | |
4304 } | |
4305 | |
4306 inforeal = g_strndup(info, od->rights.maxsiglen); | |
4307 | 4363 |
4308 if (od->icq) | 4364 if (od->icq) |
4309 aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, NULL, NULL, 0, caps_icq); | 4365 aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, NULL, NULL, 0, caps_icq); |
4310 else { | 4366 else { |
4311 flags = check_encoding(inforeal); | 4367 if (!text) { |
4312 | 4368 aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, NULL, NULL, 0, caps_aim); |
4313 if (flags == 0) { | 4369 return; |
4314 aim_bos_setprofile(od->sess, od->conn, "us-ascii", inforeal, strlen (inforeal), | 4370 } |
4315 NULL, NULL, 0, caps_aim); | 4371 |
4372 flags = oscar_encoding_check(text); | |
4373 if (flags & AIM_IMFLAGS_UNICODE) { | |
4374 msg = g_convert(text, strlen(text), "UCS-2BE", "UTF-8", NULL, &msglen, NULL); | |
4375 aim_bos_setprofile(od->sess, od->conn, "unicode-2-0", msg, (msglen > od->rights.maxsiglen ? od->rights.maxsiglen : msglen), NULL, NULL, 0, caps_aim); | |
4376 g_free(msg); | |
4377 gc->away = g_strndup(text, od->rights.maxsiglen/2); | |
4378 } else if (flags & AIM_IMFLAGS_ISO_8859_1) { | |
4379 msg = g_convert(text, strlen(text), "ISO-8859-1", "UTF-8", NULL, &msglen, NULL); | |
4380 aim_bos_setprofile(od->sess, od->conn, "iso-8859-1", msg, (msglen > od->rights.maxsiglen ? od->rights.maxsiglen : msglen), NULL, NULL, 0, caps_aim); | |
4381 g_free(msg); | |
4382 gc->away = g_strndup(text, od->rights.maxsiglen); | |
4316 } else { | 4383 } else { |
4317 unicode = g_convert (inforeal, strlen(inforeal), "UCS-2BE", "UTF-8", NULL, | 4384 msglen = strlen(text); |
4318 &unicode_len, NULL); | 4385 aim_bos_setprofile(od->sess, od->conn, "us-ascii", text, (msglen > od->rights.maxsiglen ? od->rights.maxsiglen : msglen), NULL, NULL, 0, caps_aim); |
4319 aim_bos_setprofile(od->sess, od->conn, "unicode-2-0", unicode, unicode_len, | 4386 gc->away = g_strndup(text, od->rights.maxsiglen); |
4320 NULL, NULL, 0, caps_aim); | 4387 } |
4321 g_free(unicode); | 4388 |
4322 } | 4389 if (msglen > od->rights.maxsiglen) { |
4323 } | 4390 gchar *errstr; |
4324 g_free(inforeal); | 4391 errstr = g_strdup_printf(_("The maximum profile length of %d bytes has been exceeded. " |
4392 "Gaim has truncated it for you."), od->rights.maxsiglen); | |
4393 do_error_dialog(_("Profile too long."), errstr, GAIM_WARNING); | |
4394 g_free(errstr); | |
4395 } | |
4396 | |
4397 } | |
4325 | 4398 |
4326 return; | 4399 return; |
4327 } | 4400 } |
4328 | 4401 |
4329 static void oscar_set_away_aim(struct gaim_connection *gc, struct oscar_data *od, const char *message) | 4402 static void oscar_set_away_aim(struct gaim_connection *gc, struct oscar_data *od, const char *text) |
4330 { | 4403 { |
4331 fu32_t flags; | 4404 fu32_t flags = 0; |
4332 char *unicode; | 4405 char *msg = NULL; |
4333 int unicode_len; | 4406 int msglen = 0; |
4334 | 4407 |
4335 if (od->rights.maxawaymsglen == 0) | 4408 if (od->rights.maxawaymsglen == 0) |
4336 do_error_dialog(_("Unable to set AIM away message."), | 4409 do_error_dialog(_("Unable to set AIM away message."), |
4337 _("You have probably requested to set your away message before the login procedure completed. " | 4410 _("You have probably requested to set your away message before the login procedure completed. " |
4338 "You remain in a \"present\" state; try setting it again when you are fully connected."), GAIM_ERROR); | 4411 "You remain in a \"present\" state; try setting it again when you are fully connected."), GAIM_WARNING); |
4339 | 4412 |
4340 if (gc->away) { | 4413 if (gc->away) { |
4341 g_free(gc->away); | 4414 g_free(gc->away); |
4342 gc->away = NULL; | 4415 gc->away = NULL; |
4343 } | 4416 } |
4344 | 4417 |
4345 if (!message) { | 4418 if (!text) { |
4346 aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, NULL, "", 0, caps_aim); | 4419 aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, NULL, "", 0, caps_aim); |
4347 return; | 4420 return; |
4348 } | 4421 } |
4349 | 4422 |
4350 if (strlen(message) > od->rights.maxawaymsglen) { | 4423 flags = oscar_encoding_check(text); |
4424 if (flags & AIM_IMFLAGS_UNICODE) { | |
4425 msg = g_convert(text, strlen(text), "UCS-2BE", "UTF-8", NULL, &msglen, NULL); | |
4426 aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, "unicode-2-0", msg, | |
4427 (msglen > od->rights.maxawaymsglen ? od->rights.maxawaymsglen : msglen), caps_aim); | |
4428 g_free(msg); | |
4429 gc->away = g_strndup(text, od->rights.maxawaymsglen/2); | |
4430 } else if (flags & AIM_IMFLAGS_ISO_8859_1) { | |
4431 msg = g_convert(text, strlen(text), "ISO-8859-1", "UTF-8", NULL, &msglen, NULL); | |
4432 aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, "iso-8859-1", msg, | |
4433 (msglen > od->rights.maxawaymsglen ? od->rights.maxawaymsglen : msglen), caps_aim); | |
4434 g_free(msg); | |
4435 gc->away = g_strndup(text, od->rights.maxawaymsglen); | |
4436 } else { | |
4437 msglen = strlen(text); | |
4438 aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, "us-ascii", text, | |
4439 (msglen > od->rights.maxawaymsglen ? od->rights.maxawaymsglen : msglen), caps_aim); | |
4440 gc->away = g_strndup(text, od->rights.maxawaymsglen); | |
4441 } | |
4442 | |
4443 if (msglen > od->rights.maxawaymsglen) { | |
4351 gchar *errstr; | 4444 gchar *errstr; |
4352 | 4445 |
4353 errstr = g_strdup_printf(_("The away message length of %d bytes has been exceeded. " | 4446 errstr = g_strdup_printf(_("The maximum away message length of %d bytes has been exceeded. " |
4354 "Gaim has truncated it and set you away."), od->rights.maxawaymsglen); | 4447 "Gaim has truncated it and set you away."), od->rights.maxawaymsglen); |
4355 do_error_dialog("Away message too long.", errstr, GAIM_WARNING); | 4448 do_error_dialog(_("Away message too long."), errstr, GAIM_WARNING); |
4356 g_free(errstr); | 4449 g_free(errstr); |
4357 } | |
4358 | |
4359 gc->away = g_strndup(message, od->rights.maxawaymsglen); | |
4360 flags = check_encoding(message); | |
4361 | |
4362 if (flags == 0) { | |
4363 aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, "us-ascii", gc->away, strlen(gc->away), | |
4364 caps_aim); | |
4365 } else { | |
4366 unicode = g_convert(message, strlen(message), "UCS-2BE", "UTF-8", NULL, &unicode_len, NULL); | |
4367 aim_bos_setprofile(od->sess, od->conn, NULL, NULL, 0, "unicode-2-0", unicode, unicode_len, | |
4368 caps_aim); | |
4369 g_free(unicode); | |
4370 } | 4450 } |
4371 | 4451 |
4372 return; | 4452 return; |
4373 } | 4453 } |
4374 | 4454 |
5777 | 5857 |
5778 od->direct_ims = g_slist_remove(od->direct_ims, dim); | 5858 od->direct_ims = g_slist_remove(od->direct_ims, dim); |
5779 gaim_input_remove(dim->watcher); | 5859 gaim_input_remove(dim->watcher); |
5780 aim_conn_kill(od->sess, &dim->conn); | 5860 aim_conn_kill(od->sess, &dim->conn); |
5781 g_free(dim); | 5861 g_free(dim); |
5782 } | |
5783 | |
5784 static fu32_t check_encoding(const char *utf8) | |
5785 { | |
5786 int i = 0; | |
5787 fu32_t encodingflag = 0; | |
5788 | |
5789 /* Determine how we can send this message. Per the | |
5790 * warnings elsewhere in this file, these little | |
5791 * checks determine the simplest encoding we can use | |
5792 * for a given message send using it. */ | |
5793 while (utf8[i]) { | |
5794 if ((unsigned char)utf8[i] > 0x7f) { | |
5795 /* not ASCII! */ | |
5796 encodingflag = AIM_IMFLAGS_ISO_8859_1; | |
5797 break; | |
5798 } | |
5799 i++; | |
5800 } | |
5801 while (utf8[i]) { | |
5802 /* ISO-8859-1 is 0x00-0xbf in the first byte | |
5803 * followed by 0xc0-0xc3 in the second */ | |
5804 if ((unsigned char)utf8[i] < 0x80) { | |
5805 i++; | |
5806 continue; | |
5807 } else if (((unsigned char)utf8[i] & 0xfc) == 0xc0 && | |
5808 ((unsigned char)utf8[i + 1] & 0xc0) == 0x80) { | |
5809 i += 2; | |
5810 continue; | |
5811 } | |
5812 encodingflag = AIM_IMFLAGS_UNICODE; | |
5813 break; | |
5814 } | |
5815 | |
5816 return encodingflag; | |
5817 } | |
5818 | |
5819 static fu32_t parse_encoding(const char *enc) | |
5820 { | |
5821 char *charset; | |
5822 | |
5823 /* If anything goes wrong, fall back on ASCII and print a message */ | |
5824 if (enc == NULL) { | |
5825 debug_printf("Encoding was null, that's odd\n"); | |
5826 return 0; | |
5827 } | |
5828 charset = strstr(enc, "charset="); | |
5829 if (charset == NULL) { | |
5830 debug_printf("No charset specified for info, assuming ASCII\n"); | |
5831 return 0; | |
5832 } | |
5833 charset += 8; | |
5834 if (!strcmp(charset, "\"us-ascii\"") || !strcmp(charset, "\"utf-8\"")) { | |
5835 /* UTF-8 is our native charset, ASCII is a proper subset */ | |
5836 return 0; | |
5837 } else if (!strcmp(charset, "\"iso-8859-1\"")) { | |
5838 return AIM_IMFLAGS_ISO_8859_1; | |
5839 } else if (!strcmp(charset, "\"unicode-2-0\"")) { | |
5840 return AIM_IMFLAGS_UNICODE; | |
5841 } else { | |
5842 debug_printf("Unrecognized character set '%s', using ASCII\n", charset); | |
5843 return 0; | |
5844 } | |
5845 } | 5862 } |
5846 | 5863 |
5847 G_MODULE_EXPORT void oscar_init(struct prpl *ret) { | 5864 G_MODULE_EXPORT void oscar_init(struct prpl *ret) { |
5848 struct proto_user_opt *puo; | 5865 struct proto_user_opt *puo; |
5849 ret->protocol = PROTO_OSCAR; | 5866 ret->protocol = PROTO_OSCAR; |