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