Mercurial > pidgin
annotate src/protocols/yahoo/util.c @ 11249:b4b1be482b4e
[gaim-migrate @ 13418]
sf patch #1235519, from Sadrul Habib Chowdhury
This is a pretty big patch that makes Gaim correctly save and restore
the current status (away/available, away message, available message,
invisible, etc).
The GaimGtkStatusBoxWidget thing I think defaults to "Available"
every time its created, which overrides the setting that was saved
to the XML file. So that still needs to be fixed before this will
really work.
Anyway, mad props to Sadrul for putting up with my requests on this patch
committer: Tailor Script <tailor@pidgin.im>
| author | Mark Doliner <mark@kingant.net> |
|---|---|
| date | Sat, 13 Aug 2005 05:22:09 +0000 |
| parents | 1e6bdc7175e9 |
| children | f4e58e94ced3 |
| rev | line source |
|---|---|
| 6513 | 1 /* |
| 2 * gaim | |
| 3 * | |
| 4 * Some code copyright 2003 Tim Ringenbach <omarvo@hotmail.com> | |
| 5 * (marv on irc.freenode.net) | |
| 6 * | |
| 7 * This program is free software; you can redistribute it and/or modify | |
| 8 * it under the terms of the GNU General Public License as published by | |
| 9 * the Free Software Foundation; either version 2 of the License, or | |
| 10 * (at your option) any later version. | |
| 11 * | |
| 12 * This program is distributed in the hope that it will be useful, | |
| 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 * GNU General Public License for more details. | |
| 16 * | |
| 17 * You should have received a copy of the GNU General Public License | |
| 18 * along with this program; if not, write to the Free Software | |
| 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 20 * | |
| 21 */ | |
| 22 | |
| 23 #ifdef HAVE_CONFIG_H | |
| 24 #include "config.h" | |
| 25 #endif | |
| 26 | |
| 10023 | 27 #include "debug.h" |
| 28 #include "internal.h" | |
| 6513 | 29 #include "prpl.h" |
| 10023 | 30 |
| 7827 | 31 #include "yahoo.h" |
| 6513 | 32 |
| 6546 | 33 #include <string.h> |
| 34 | |
| 7827 | 35 /** |
| 36 * Encode some text to send to the yahoo server. | |
| 37 * | |
| 38 * @param gc The connection handle. | |
| 39 * @param str The null terminated utf8 string to encode. | |
| 40 * @param utf8 If not @c NULL, whether utf8 is okay or not. | |
| 41 * Even if it is okay, we may not use it. If we | |
| 42 * used it, we set this to @c TRUE, else to | |
| 43 * @c FALSE. If @c NULL, false is assumed, and | |
| 44 * it is not dereferenced. | |
| 45 * @return The g_malloced string in the appropriate encoding. | |
| 46 */ | |
| 47 char *yahoo_string_encode(GaimConnection *gc, const char *str, gboolean *utf8) | |
| 48 { | |
| 9164 | 49 struct yahoo_data *yd = gc->proto_data; |
| 7827 | 50 char *ret; |
| 10504 | 51 const char *to_codeset; |
| 7827 | 52 |
| 9164 | 53 if (yd->jp && utf8 && *utf8) |
| 54 *utf8 = FALSE; | |
| 55 | |
| 7827 | 56 if (utf8 && *utf8) /* FIXME: maybe don't use utf8 if it'll fit in latin1 */ |
| 57 return g_strdup(str); | |
| 58 | |
| 9164 | 59 if (yd->jp) |
| 60 to_codeset = "SHIFT_JIS"; | |
| 61 else | |
| 62 to_codeset = "ISO-8859-1"; | |
| 7827 | 63 |
| 8955 | 64 ret = g_convert_with_fallback(str, strlen(str), to_codeset, "UTF-8", "?", NULL, NULL, NULL); |
| 7827 | 65 if (ret) |
| 66 return ret; | |
| 67 else | |
| 68 return g_strdup(""); | |
| 69 } | |
| 70 | |
| 71 /** | |
| 72 * Decode some text received from the server. | |
| 73 * | |
| 74 * @param gc The gc handle. | |
| 75 * @param str The null terminated string to decode. | |
| 76 * @param utf8 Did the server tell us it was supposed to be utf8? | |
| 77 * @return The decoded, utf-8 string, which must be g_free()'d. | |
| 78 */ | |
| 79 char *yahoo_string_decode(GaimConnection *gc, const char *str, gboolean utf8) | |
| 80 { | |
| 9164 | 81 struct yahoo_data *yd = gc->proto_data; |
| 7827 | 82 char *ret; |
| 83 char *from_codeset; | |
| 84 | |
| 85 if (utf8) { | |
| 86 if (g_utf8_validate(str, -1, NULL)) | |
| 87 return g_strdup(str); | |
| 88 } | |
| 89 | |
| 9164 | 90 if (yd->jp) |
| 91 from_codeset = "SHIFT_JIS"; | |
| 92 else | |
| 93 from_codeset = "ISO-8859-1"; | |
| 7827 | 94 |
| 95 ret = g_convert_with_fallback(str, strlen(str), "UTF-8", from_codeset, NULL, NULL, NULL, NULL); | |
| 96 | |
| 97 if (ret) | |
| 98 return ret; | |
| 99 else | |
| 100 return g_strdup(""); | |
| 101 } | |
| 102 | |
| 103 | |
| 6513 | 104 |
| 105 /* | |
| 106 * I found these on some website but i don't know that they actually | |
|
8735
92cbf9713795
[gaim-migrate @ 9490]
Christian Hammond <chipx86@chipx86.com>
parents:
8533
diff
changeset
|
107 * work (or are supposed to work). I didn't implement them yet. |
| 6513 | 108 * |
| 109 * [0;30m ---black | |
| 110 * [1;37m ---white | |
| 111 * [0;37m ---tan | |
| 112 * [0;38m ---light black | |
| 113 * [1;39m ---dark blue | |
| 114 * [0;32m ---green | |
| 115 * [0;33m ---yellow | |
| 116 * [0;35m ---pink | |
| 117 * [1;35m ---purple | |
| 118 * [1;30m ---light blue | |
| 119 * [0;31m ---red | |
| 120 * [0;34m ---blue | |
| 121 * [0;36m ---aqua | |
| 122 * (shift+comma)lyellow(shift+period) ---light yellow | |
| 123 * (shift+comma)lgreen(shift+period) ---light green | |
| 124 [2;30m <--white out | |
| 125 | |
| 126 */ | |
| 127 | |
| 128 | |
| 129 static GHashTable *ht = NULL; | |
| 130 | |
| 131 void yahoo_init_colorht() | |
| 132 { | |
| 133 ht = g_hash_table_new(g_str_hash, g_str_equal); | |
| 6629 | 134 /* the numbers in comments are what gyach uses, but i think they're incorrect */ |
| 6513 | 135 g_hash_table_insert(ht, "30", "<FONT COLOR=\"#000000\">"); /* black */ |
| 136 g_hash_table_insert(ht, "31", "<FONT COLOR=\"#0000FF\">"); /* blue */ | |
| 137 g_hash_table_insert(ht, "32", "<FONT COLOR=\"#008080\">"); /* cyan */ /* 00b2b2 */ | |
| 138 g_hash_table_insert(ht, "33", "<FONT COLOR=\"#808080\">"); /* gray */ /* 808080 */ | |
| 139 g_hash_table_insert(ht, "34", "<FONT COLOR=\"#008000\">"); /* green */ /* 00c200 */ | |
| 140 g_hash_table_insert(ht, "35", "<FONT COLOR=\"#FF0080\">"); /* pink */ /* ffafaf */ | |
| 141 g_hash_table_insert(ht, "36", "<FONT COLOR=\"#800080\">"); /* purple */ /* b200b2 */ | |
| 142 g_hash_table_insert(ht, "37", "<FONT COLOR=\"#FF8000\">"); /* orange */ /* ffff00 */ | |
| 143 g_hash_table_insert(ht, "38", "<FONT COLOR=\"#FF0000\">"); /* red */ | |
| 144 g_hash_table_insert(ht, "39", "<FONT COLOR=\"#808000\">"); /* olive */ /* 546b50 */ | |
| 145 | |
| 146 g_hash_table_insert(ht, "1", "<B>"); | |
| 147 g_hash_table_insert(ht, "x1", "</B>"); | |
| 148 g_hash_table_insert(ht, "2", "<I>"); | |
| 149 g_hash_table_insert(ht, "x2", "</I>"); | |
| 150 g_hash_table_insert(ht, "4", "<U>"); | |
| 151 g_hash_table_insert(ht, "x4", "</U>"); | |
| 152 | |
| 6629 | 153 /* these just tell us the text they surround is supposed |
| 154 * to be a link. gaim figures that out on its own so we | |
| 155 * just ignore it. | |
| 156 */ | |
| 157 g_hash_table_insert(ht, "l", ""); /* link start */ | |
| 158 g_hash_table_insert(ht, "xl", ""); /* link end */ | |
| 159 | |
| 160 | |
| 6513 | 161 g_hash_table_insert(ht, "<black>", "<FONT COLOR=\"#000000\">"); |
| 162 g_hash_table_insert(ht, "<blue>", "<FONT COLOR=\"#0000FF\">"); | |
| 163 g_hash_table_insert(ht, "<cyan>", "<FONT COLOR=\"#008284\">"); | |
| 164 g_hash_table_insert(ht, "<gray>", "<FONT COLOR=\"#848284\">"); | |
| 165 g_hash_table_insert(ht, "<green>", "<FONT COLOR=\"#008200\">"); | |
| 166 g_hash_table_insert(ht, "<pink>", "<FONT COLOR=\"#FF0084\">"); | |
| 167 g_hash_table_insert(ht, "<purple>", "<FONT COLOR=\"#840084\">"); | |
| 168 g_hash_table_insert(ht, "<orange>", "<FONT COLOR=\"#FF8000\">"); | |
| 169 g_hash_table_insert(ht, "<red>", "<FONT COLOR=\"#FF0000\">"); | |
| 170 g_hash_table_insert(ht, "<yellow>", "<FONT COLOR=\"#848200\">"); | |
| 171 | |
| 172 g_hash_table_insert(ht, "</black>", "</FONT>"); | |
| 173 g_hash_table_insert(ht, "</blue>", "</FONT>"); | |
| 174 g_hash_table_insert(ht, "</cyan>", "</FONT>"); | |
| 175 g_hash_table_insert(ht, "</gray>", "</FONT>"); | |
| 176 g_hash_table_insert(ht, "</green>", "</FONT>"); | |
| 177 g_hash_table_insert(ht, "</pink>", "</FONT>"); | |
| 178 g_hash_table_insert(ht, "</purple>", "</FONT>"); | |
| 179 g_hash_table_insert(ht, "</orange>", "</FONT>"); | |
| 180 g_hash_table_insert(ht, "</red>", "</FONT>"); | |
| 181 g_hash_table_insert(ht, "</yellow>", "</FONT>"); | |
| 182 | |
| 183 /* remove these once we have proper support for <FADE> and <ALT> */ | |
| 184 g_hash_table_insert(ht, "</fade>", ""); | |
| 185 g_hash_table_insert(ht, "</alt>", ""); | |
| 8375 | 186 |
| 187 /* these are the normal html yahoo sends (besides <font>). | |
| 188 * anything else will get turned into <tag>, so if I forgot | |
| 189 * about something, please add it. Why Yahoo! has to send unescaped | |
| 190 * <'s and >'s that aren't supposed to be html is beyond me. | |
| 191 */ | |
| 192 g_hash_table_insert(ht, "<b>", "<b>"); | |
| 193 g_hash_table_insert(ht, "<i>", "<i>"); | |
| 194 g_hash_table_insert(ht, "<u>", "<u>"); | |
| 195 | |
| 196 g_hash_table_insert(ht, "</b>", "</b>"); | |
| 197 g_hash_table_insert(ht, "</i>", "</i>"); | |
| 198 g_hash_table_insert(ht, "</u>", "</u>"); | |
| 8440 | 199 g_hash_table_insert(ht, "</font>", "</font>"); |
| 6513 | 200 } |
| 201 | |
| 202 void yahoo_dest_colorht() | |
| 203 { | |
| 204 g_hash_table_destroy(ht); | |
| 205 } | |
| 206 | |
| 6629 | 207 static int point_to_html(int x) |
| 208 { | |
| 209 if (x < 9) | |
| 210 return 1; | |
| 211 if (x < 11) | |
| 212 return 2; | |
| 213 if (x < 13) | |
| 214 return 3; | |
| 215 if (x < 17) | |
| 216 return 4; | |
| 217 if (x < 25) | |
| 218 return 5; | |
| 219 if (x < 35) | |
| 220 return 6; | |
| 221 return 7; | |
| 222 } | |
| 10380 | 223 |
| 224 /* The Yahoo size tag is actually an absz tag; convert it to an HTML size, and include both tags */ | |
| 6629 | 225 static void _font_tags_fix_size(GString *tag, GString *dest) |
| 226 { | |
| 227 char *x, *end; | |
| 228 int size; | |
| 229 | |
| 230 if (((x = strstr(tag->str, "size"))) && ((x = strchr(tag->str, '=')))) { | |
| 231 while (*x && !g_ascii_isdigit(*x)) | |
| 232 x++; | |
| 233 if (*x) { | |
| 10380 | 234 int htmlsize; |
| 235 | |
| 6629 | 236 size = strtol(x, &end, 10); |
| 10380 | 237 htmlsize = point_to_html(size); |
| 6629 | 238 g_string_append_len(dest, tag->str, x - tag->str); |
| 10380 | 239 g_string_append_printf(dest, "%d", htmlsize); |
| 240 g_string_append_printf(dest, "\" absz=\"%d", size); | |
| 6629 | 241 g_string_append(dest, end); |
| 242 } else { | |
| 243 g_string_append(dest, tag->str); | |
| 244 return; | |
| 245 } | |
| 246 } else { | |
| 247 g_string_append(dest, tag->str); | |
| 248 return; | |
| 249 } | |
| 250 } | |
| 251 | |
| 252 char *yahoo_codes_to_html(const char *x) | |
| 6513 | 253 { |
| 254 GString *s, *tmp; | |
| 6629 | 255 int i, j, xs, nomoreendtags = 0; /* s/endtags/closinganglebrackets */ |
| 6513 | 256 char *match, *ret; |
| 257 | |
| 258 s = g_string_sized_new(strlen(x)); | |
| 259 | |
| 260 for (i = 0, xs = strlen(x); i < xs; i++) { | |
| 261 if ((x[i] == 0x1b) && (x[i+1] == '[')) { | |
| 262 j = i + 1; | |
| 263 | |
| 264 while (j++ < xs) { | |
| 265 if (x[j] != 'm') | |
| 266 continue; | |
| 267 else { | |
| 268 tmp = g_string_new_len(x + i + 2, j - i - 2); | |
| 6621 | 269 if (tmp->str[0] == '#') |
| 6513 | 270 g_string_append_printf(s, "<FONT COLOR=\"%s\">", tmp->str); |
| 6546 | 271 else if ((match = (char *) g_hash_table_lookup(ht, tmp->str))) |
| 6513 | 272 g_string_append(s, match); |
| 273 else { | |
| 274 gaim_debug(GAIM_DEBUG_ERROR, "yahoo", | |
| 275 "Unknown ansi code 'ESC[%sm'.\n", tmp->str); | |
| 276 g_string_free(tmp, TRUE); | |
| 277 break; | |
| 278 } | |
| 279 | |
| 280 i = j; | |
| 281 g_string_free(tmp, TRUE); | |
| 282 break; | |
| 283 } | |
| 284 } | |
| 285 | |
| 286 | |
| 287 } else if (!nomoreendtags && (x[i] == '<')) { | |
| 6629 | 288 j = i; |
| 6513 | 289 |
| 290 while (j++ < xs) { | |
| 291 if (x[j] != '>') | |
| 292 if (j == xs) { | |
| 8375 | 293 g_string_append(s, "<"); |
| 6513 | 294 nomoreendtags = 1; |
| 295 } | |
| 296 else | |
| 297 continue; | |
| 298 else { | |
| 299 tmp = g_string_new_len(x + i, j - i + 1); | |
| 300 g_string_ascii_down(tmp); | |
| 301 | |
| 6546 | 302 if ((match = (char *) g_hash_table_lookup(ht, tmp->str))) |
| 6513 | 303 g_string_append(s, match); |
| 6629 | 304 else if (!strncmp(tmp->str, "<fade ", 6) || |
| 305 !strncmp(tmp->str, "<alt ", 5) || | |
| 306 !strncmp(tmp->str, "<snd ", 5)) { | |
| 6513 | 307 |
| 6629 | 308 /* remove this if gtkimhtml ever supports any of these */ |
| 6513 | 309 i = j; |
| 310 g_string_free(tmp, TRUE); | |
| 311 break; | |
| 312 | |
| 6629 | 313 } else if (!strncmp(tmp->str, "<font ", 6)) { |
| 314 _font_tags_fix_size(tmp, s); | |
| 6513 | 315 } else { |
| 8375 | 316 g_string_append(s, "<"); |
| 6513 | 317 g_string_free(tmp, TRUE); |
| 318 break; | |
| 319 } | |
| 320 | |
| 321 i = j; | |
| 322 g_string_free(tmp, TRUE); | |
| 323 break; | |
| 324 } | |
| 325 | |
| 326 } | |
| 327 | |
| 328 | |
| 329 | |
| 330 } else { | |
| 8375 | 331 if (x[i] == '<') |
| 332 g_string_append(s, "<"); | |
| 333 else if (x[i] == '>') | |
| 334 g_string_append(s, ">"); | |
| 8440 | 335 else if (x[i] == '&') |
| 336 g_string_append(s, "&"); | |
| 337 else if (x[i] == '"') | |
| 338 g_string_append(s, """); | |
| 8375 | 339 else |
| 340 g_string_append_c(s, x[i]); | |
| 6513 | 341 } |
| 342 } | |
| 343 | |
| 344 ret = s->str; | |
| 345 g_string_free(s, FALSE); | |
| 6629 | 346 gaim_debug(GAIM_DEBUG_MISC, "yahoo", "yahoo_codes_to_html: Returning string: '%s'.\n", ret); |
| 6513 | 347 return ret; |
| 348 } | |
| 6629 | 349 |
| 350 /* borrowed from gtkimhtml */ | |
| 351 #define MAX_FONT_SIZE 7 | |
| 10899 | 352 #define POINT_SIZE(x) (_point_sizes [MIN ((x > 0 ? x : 1), MAX_FONT_SIZE) - 1]) |
| 6629 | 353 static gint _point_sizes [] = { 8, 10, 12, 14, 20, 30, 40 }; |
| 354 | |
| 355 enum fatype { size, color, face, junk }; | |
| 356 typedef struct { | |
| 357 enum fatype type; | |
| 358 union { | |
| 359 int size; | |
| 360 char *color; | |
| 361 char *face; | |
| 362 char *junk; | |
| 363 } u; | |
| 364 } fontattr; | |
| 365 | |
| 366 static void fontattr_free(fontattr *f) | |
| 367 { | |
| 368 if (f->type == color) | |
| 369 g_free(f->u.color); | |
| 370 else if (f->type == face) | |
| 371 g_free(f->u.face); | |
| 372 g_free(f); | |
| 373 } | |
| 374 | |
| 375 static void yahoo_htc_queue_cleanup(GQueue *q) | |
| 376 { | |
| 377 char *tmp; | |
| 378 | |
| 379 while ((tmp = g_queue_pop_tail(q))) | |
| 380 g_free(tmp); | |
| 381 g_queue_free(q); | |
| 382 } | |
| 383 | |
| 384 static void _parse_font_tag(const char *src, GString *dest, int *i, int *j, | |
| 385 int len, GQueue *colors, GQueue *tags, GQueue *ftattr) | |
| 386 { | |
| 387 | |
| 388 int m, n, vstart; | |
| 389 gboolean quote = 0, done = 0; | |
| 390 | |
| 391 m = *j; | |
| 392 | |
| 393 while (1) { | |
| 394 m++; | |
| 395 | |
| 396 if (m >= len) { | |
| 397 g_string_append(dest, &src[*i]); | |
| 398 *i = len; | |
| 399 break; | |
| 400 } | |
| 401 | |
| 402 if (src[m] == '=') { | |
| 403 n = vstart = m; | |
| 404 while (1) { | |
| 405 n++; | |
| 406 | |
| 407 if (n >= len) { | |
| 408 m = n; | |
| 409 break; | |
| 410 } | |
| 411 | |
| 6631 | 412 if (src[n] == '"') { |
| 6629 | 413 if (!quote) { |
| 414 quote = 1; | |
| 415 vstart = n; | |
| 416 continue; | |
| 417 } else { | |
| 418 done = 1; | |
| 419 } | |
| 6631 | 420 } |
| 6629 | 421 |
| 422 if (!quote && ((src[n] == ' ') || (src[n] == '>'))) | |
| 423 done = 1; | |
| 424 | |
| 425 if (done) { | |
| 426 if (!g_ascii_strncasecmp(&src[*j+1], "FACE", m - *j - 1)) { | |
| 427 fontattr *f; | |
| 428 | |
| 429 f = g_new(fontattr, 1); | |
| 430 f->type = face; | |
| 431 f->u.face = g_strndup(&src[vstart+1], n-vstart-1); | |
| 432 if (!ftattr) | |
| 433 ftattr = g_queue_new(); | |
| 434 g_queue_push_tail(ftattr, f); | |
| 435 m = n; | |
| 436 break; | |
| 437 } else if (!g_ascii_strncasecmp(&src[*j+1], "SIZE", m - *j - 1)) { | |
| 438 fontattr *f; | |
| 439 | |
| 440 f = g_new(fontattr, 1); | |
| 441 f->type = size; | |
| 442 f->u.size = POINT_SIZE(strtol(&src[vstart+1], NULL, 10)); | |
| 443 if (!ftattr) | |
| 444 ftattr = g_queue_new(); | |
| 445 g_queue_push_tail(ftattr, f); | |
| 446 m = n; | |
| 447 break; | |
| 448 } else if (!g_ascii_strncasecmp(&src[*j+1], "COLOR", m - *j - 1)) { | |
| 449 fontattr *f; | |
| 450 | |
| 451 f = g_new(fontattr, 1); | |
| 452 f->type = color; | |
| 453 f->u.color = g_strndup(&src[vstart+1], n-vstart-1); | |
| 454 if (!ftattr) | |
| 455 ftattr = g_queue_new(); | |
| 456 g_queue_push_head(ftattr, f); | |
| 457 m = n; | |
| 458 break; | |
| 459 } else { | |
| 460 fontattr *f; | |
| 461 | |
| 462 f = g_new(fontattr, 1); | |
| 463 f->type = junk; | |
| 464 f->u.junk = g_strndup(&src[*j+1], n-*j); | |
| 465 if (!ftattr) | |
| 466 ftattr = g_queue_new(); | |
| 467 g_queue_push_tail(ftattr, f); | |
| 468 m = n; | |
| 469 break; | |
| 470 } | |
| 471 | |
| 472 } | |
| 473 } | |
| 474 } | |
| 475 | |
| 476 if (src[m] == ' ') | |
| 477 *j = m; | |
| 478 | |
| 479 | |
| 480 | |
| 481 if (src[m] == '>') { | |
| 482 gboolean needendtag = 0; | |
| 483 fontattr *f; | |
| 484 GString *tmp = g_string_new(NULL); | |
| 485 char *colorstr; | |
| 486 | |
| 487 if (!g_queue_is_empty(ftattr)) { | |
| 488 while ((f = g_queue_pop_tail(ftattr))) { | |
| 489 switch (f->type) { | |
| 490 case size: | |
| 491 if (!needendtag) { | |
| 492 needendtag = 1; | |
| 493 g_string_append(dest, "<font "); | |
| 494 } | |
| 495 | |
| 496 g_string_append_printf(dest, "size=\"%d\" ", f->u.size); | |
| 497 fontattr_free(f); | |
| 498 break; | |
| 499 case face: | |
| 500 if (!needendtag) { | |
| 501 needendtag = 1; | |
| 502 g_string_append(dest, "<font "); | |
| 503 } | |
| 504 | |
| 505 g_string_append_printf(dest, "face=\"%s\" ", f->u.face); | |
| 506 fontattr_free(f); | |
| 507 break; | |
| 508 case junk: | |
| 509 if (!needendtag) { | |
| 510 needendtag = 1; | |
| 511 g_string_append(dest, "<font "); | |
| 512 } | |
| 513 | |
| 514 g_string_append(dest, f->u.junk); | |
| 515 fontattr_free(f); | |
| 516 break; | |
| 517 | |
| 518 case color: | |
| 519 if (needendtag) { | |
| 520 g_string_append(tmp, "</font>"); | |
| 521 dest->str[dest->len-1] = '>'; | |
| 522 needendtag = 0; | |
| 523 } | |
| 524 | |
| 525 colorstr = g_queue_peek_tail(colors); | |
| 526 g_string_append(tmp, colorstr ? colorstr : "\033[#000000m"); | |
| 527 g_string_append_printf(dest, "\033[%sm", f->u.color); | |
| 528 g_queue_push_tail(colors, g_strdup_printf("\033[%sm", f->u.color)); | |
| 529 fontattr_free(f); | |
| 530 break; | |
| 531 } | |
| 532 } | |
| 533 | |
| 534 g_queue_free(ftattr); | |
| 535 ftattr = NULL; | |
| 536 | |
| 537 if (needendtag) { | |
| 538 dest->str[dest->len-1] = '>'; | |
| 539 g_queue_push_tail(tags, g_strdup("</font>")); | |
| 540 g_string_free(tmp, TRUE); | |
| 541 } else { | |
| 542 g_queue_push_tail(tags, tmp->str); | |
| 543 g_string_free(tmp, FALSE); | |
| 544 } | |
| 545 } | |
| 546 | |
| 547 *i = *j = m; | |
| 548 break; | |
| 549 } | |
| 550 } | |
| 551 | |
| 552 } | |
| 553 | |
| 554 char *yahoo_html_to_codes(const char *src) | |
| 555 { | |
| 6631 | 556 int i, j, len; |
| 6629 | 557 GString *dest; |
| 558 char *ret, *esc; | |
| 559 GQueue *colors, *tags; | |
| 560 GQueue *ftattr = NULL; | |
| 8440 | 561 gboolean no_more_specials = FALSE; |
| 6629 | 562 |
| 563 | |
| 564 colors = g_queue_new(); | |
| 565 tags = g_queue_new(); | |
| 566 | |
| 567 dest = g_string_sized_new(strlen(src)); | |
| 568 | |
| 569 for (i = 0, len = strlen(src); i < len; i++) { | |
| 570 | |
| 8440 | 571 if (!no_more_specials && src[i] == '<') { |
| 6629 | 572 j = i; |
| 573 | |
| 574 while (1) { | |
| 575 j++; | |
| 576 | |
| 577 if (j >= len) { /* no '>' */ | |
| 8440 | 578 g_string_append_c(dest, src[i]); |
| 579 no_more_specials = TRUE; | |
| 6629 | 580 break; |
| 581 } | |
| 582 | |
| 583 if (src[j] == '<') { | |
| 8440 | 584 /* FIXME: This doesn't convert outgoing entities. |
| 585 * However, I suspect this case may never | |
| 586 * happen anymore because of the entities. | |
| 587 */ | |
| 6629 | 588 g_string_append_len(dest, &src[i], j - i); |
| 589 i = j - 1; | |
| 590 if (ftattr) { | |
| 591 fontattr *f; | |
| 592 | |
| 593 while ((f = g_queue_pop_head(ftattr))) | |
| 594 fontattr_free(f); | |
| 595 g_queue_free(ftattr); | |
| 596 ftattr = NULL; | |
| 597 } | |
| 598 break; | |
| 599 } | |
| 600 | |
| 601 if (src[j] == ' ') { | |
| 602 if (!g_ascii_strncasecmp(&src[i+1], "BODY", j - i - 1)) { | |
| 603 char *t = strchr(&src[j], '>'); | |
| 604 if (!t) { | |
| 605 g_string_append(dest, &src[i]); | |
| 606 i = len; | |
| 607 break; | |
| 608 } else { | |
| 609 i = t - src; | |
| 610 break; | |
| 611 } | |
| 8533 | 612 } else if (!g_ascii_strncasecmp(&src[i+1], "A HREF=\"", j - i - 1)) { |
| 613 j += 7; | |
| 614 g_string_append(dest, "\033[lm"); | |
| 615 while (1) { | |
| 616 g_string_append_c(dest, src[j]); | |
| 617 if (++j >= len) { | |
| 8480 | 618 i = len; |
| 619 break; | |
| 620 } | |
| 8533 | 621 if (src[j] == '"') { |
| 622 g_string_append(dest, "\033[xlm"); | |
| 623 while (1) { | |
| 624 if (++j >= len) { | |
| 625 i = len; | |
| 626 break; | |
| 627 } | |
| 628 if (!g_ascii_strncasecmp(&src[j], "</A>", 4)) { | |
| 629 j += 3; | |
| 630 break; | |
| 631 } | |
| 632 } | |
| 633 i = j; | |
| 8480 | 634 break; |
| 635 } | |
| 636 } | |
| 6629 | 637 } else if (g_ascii_strncasecmp(&src[i+1], "FONT", j - i - 1)) { /* not interested! */ |
| 638 while (1) { | |
| 639 if (++j >= len) { | |
| 640 g_string_append(dest, &src[i]); | |
| 641 i = len; | |
| 642 break; | |
| 643 } | |
| 644 if (src[j] == '>') { | |
| 645 g_string_append_len(dest, &src[i], j - i + 1); | |
| 646 i = j; | |
| 647 break; | |
| 648 } | |
| 649 } | |
| 650 } else { /* yay we have a font tag */ | |
| 651 _parse_font_tag(src, dest, &i, &j, len, colors, tags, ftattr); | |
| 652 } | |
| 653 | |
| 654 break; | |
| 655 } | |
| 656 | |
| 657 if (src[j] == '>') { | |
| 8440 | 658 /* This has some problems like the FIXME for the |
| 659 * '<' case. and like that case, I suspect the case | |
| 660 * that this has problems is won't happen anymore anyway. | |
| 661 */ | |
| 6629 | 662 int sublen = j - i - 1; |
| 663 | |
| 664 if (sublen) { | |
| 665 if (!g_ascii_strncasecmp(&src[i+1], "B", sublen)) { | |
| 666 g_string_append(dest, "\033[1m"); | |
| 667 } else if (!g_ascii_strncasecmp(&src[i+1], "/B", sublen)) { | |
| 668 g_string_append(dest, "\033[x1m"); | |
| 669 } else if (!g_ascii_strncasecmp(&src[i+1], "I", sublen)) { | |
| 670 g_string_append(dest, "\033[2m"); | |
| 671 } else if (!g_ascii_strncasecmp(&src[i+1], "/I", sublen)) { | |
| 672 g_string_append(dest, "\033[x2m"); | |
| 673 } else if (!g_ascii_strncasecmp(&src[i+1], "U", sublen)) { | |
| 674 g_string_append(dest, "\033[4m"); | |
| 675 } else if (!g_ascii_strncasecmp(&src[i+1], "/U", sublen)) { | |
| 676 g_string_append(dest, "\033[x4m"); | |
| 8480 | 677 } else if (!g_ascii_strncasecmp(&src[i+1], "/A", sublen)) { |
| 678 g_string_append(dest, "\033[xlm"); | |
| 8455 | 679 } else if (!g_ascii_strncasecmp(&src[i+1], "BR", sublen)) { |
| 680 g_string_append_c(dest, '\n'); | |
| 6629 | 681 } else if (!g_ascii_strncasecmp(&src[i+1], "/BODY", sublen)) { |
| 682 /* mmm, </body> tags. *BURP* */ | |
| 683 } else if (!g_ascii_strncasecmp(&src[i+1], "/FONT", sublen) && g_queue_peek_tail(tags)) { | |
| 684 char *etag, *cl; | |
| 685 | |
| 686 etag = g_queue_pop_tail(tags); | |
| 687 if (etag) { | |
| 688 g_string_append(dest, etag); | |
| 689 if (!strcmp(etag, "</font>")) { | |
| 690 cl = g_queue_pop_tail(colors); | |
| 691 if (cl) | |
| 692 g_free(cl); | |
| 693 } | |
| 694 g_free(etag); | |
| 695 } | |
| 696 } else { | |
| 697 g_string_append_len(dest, &src[i], j - i + 1); | |
| 698 } | |
| 699 } else { | |
| 700 g_string_append_len(dest, &src[i], j - i + 1); | |
| 701 } | |
| 702 | |
| 703 i = j; | |
| 704 break; | |
| 705 } | |
| 706 | |
| 707 } | |
| 708 | |
| 709 } else { | |
| 8440 | 710 if (((len - i) >= 4) && !strncmp(&src[i], "<", 4)) { |
| 711 g_string_append_c(dest, '<'); | |
| 712 i += 3; | |
| 713 } else if (((len - i) >= 4) && !strncmp(&src[i], ">", 4)) { | |
| 714 g_string_append_c(dest, '>'); | |
| 715 i += 3; | |
| 716 } else if (((len - i) >= 5) && !strncmp(&src[i], "&", 4)) { | |
| 717 g_string_append_c(dest, '&'); | |
| 718 i += 4; | |
| 719 } else if (((len - i) >= 6) && !strncmp(&src[i], """, 4)) { | |
| 720 g_string_append_c(dest, '"'); | |
| 721 i += 5; | |
| 722 } else { | |
| 723 g_string_append_c(dest, src[i]); | |
| 724 } | |
| 6629 | 725 } |
| 726 } | |
| 727 | |
| 728 ret = dest->str; | |
| 729 g_string_free(dest, FALSE); | |
| 730 | |
| 731 esc = g_strescape(ret, NULL); | |
| 732 gaim_debug(GAIM_DEBUG_MISC, "yahoo", "yahoo_html_to_codes: Returning string: '%s'.\n", esc); | |
| 733 g_free(esc); | |
| 734 | |
| 735 yahoo_htc_queue_cleanup(colors); | |
| 736 yahoo_htc_queue_cleanup(tags); | |
| 737 | |
| 738 return ret; | |
| 739 } |
