Mercurial > pidgin
annotate src/protocols/yahoo/util.c @ 10343:ee4f477fc8cf
[gaim-migrate @ 11553]
Minor tweaks to the blist and status xml reading code. These functions
don't expect the filename to be called "blist.xml" and "status.xml"
anymore. Some guy wanted this because he wants to try to add some
sort of AIM buddy list importing, or something. I think.
committer: Tailor Script <tailor@pidgin.im>
| author | Mark Doliner <mark@kingant.net> |
|---|---|
| date | Fri, 10 Dec 2004 05:49:01 +0000 |
| parents | 34bce9529cf4 |
| children | bed8d9a7bb88 |
| 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; |
| 51 char *to_codeset; | |
| 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 } | |
| 223 static void _font_tags_fix_size(GString *tag, GString *dest) | |
| 224 { | |
| 225 char *x, *end; | |
| 226 int size; | |
| 227 | |
| 228 if (((x = strstr(tag->str, "size"))) && ((x = strchr(tag->str, '=')))) { | |
| 229 while (*x && !g_ascii_isdigit(*x)) | |
| 230 x++; | |
| 231 if (*x) { | |
| 232 size = strtol(x, &end, 10); | |
| 233 size = point_to_html(size); | |
| 234 g_string_append_len(dest, tag->str, x - tag->str); | |
| 235 g_string_append_printf(dest, "%d", size); | |
| 236 g_string_append(dest, end); | |
| 237 } else { | |
| 238 g_string_append(dest, tag->str); | |
| 239 return; | |
| 240 } | |
| 241 } else { | |
| 242 g_string_append(dest, tag->str); | |
| 243 return; | |
| 244 } | |
| 245 } | |
| 246 | |
| 247 char *yahoo_codes_to_html(const char *x) | |
| 6513 | 248 { |
| 249 GString *s, *tmp; | |
| 6629 | 250 int i, j, xs, nomoreendtags = 0; /* s/endtags/closinganglebrackets */ |
| 6513 | 251 char *match, *ret; |
| 252 | |
| 253 | |
| 254 s = g_string_sized_new(strlen(x)); | |
| 255 | |
| 256 for (i = 0, xs = strlen(x); i < xs; i++) { | |
| 257 if ((x[i] == 0x1b) && (x[i+1] == '[')) { | |
| 258 j = i + 1; | |
| 259 | |
| 260 while (j++ < xs) { | |
| 261 if (x[j] != 'm') | |
| 262 continue; | |
| 263 else { | |
| 264 tmp = g_string_new_len(x + i + 2, j - i - 2); | |
| 6621 | 265 if (tmp->str[0] == '#') |
| 6513 | 266 g_string_append_printf(s, "<FONT COLOR=\"%s\">", tmp->str); |
| 6546 | 267 else if ((match = (char *) g_hash_table_lookup(ht, tmp->str))) |
| 6513 | 268 g_string_append(s, match); |
| 269 else { | |
| 270 gaim_debug(GAIM_DEBUG_ERROR, "yahoo", | |
| 271 "Unknown ansi code 'ESC[%sm'.\n", tmp->str); | |
| 272 g_string_free(tmp, TRUE); | |
| 273 break; | |
| 274 } | |
| 275 | |
| 276 i = j; | |
| 277 g_string_free(tmp, TRUE); | |
| 278 break; | |
| 279 } | |
| 280 } | |
| 281 | |
| 282 | |
| 283 } else if (!nomoreendtags && (x[i] == '<')) { | |
| 6629 | 284 j = i; |
| 6513 | 285 |
| 286 while (j++ < xs) { | |
| 287 if (x[j] != '>') | |
| 288 if (j == xs) { | |
| 8375 | 289 g_string_append(s, "<"); |
| 6513 | 290 nomoreendtags = 1; |
| 291 } | |
| 292 else | |
| 293 continue; | |
| 294 else { | |
| 295 tmp = g_string_new_len(x + i, j - i + 1); | |
| 296 g_string_ascii_down(tmp); | |
| 297 | |
| 6546 | 298 if ((match = (char *) g_hash_table_lookup(ht, tmp->str))) |
| 6513 | 299 g_string_append(s, match); |
| 6629 | 300 else if (!strncmp(tmp->str, "<fade ", 6) || |
| 301 !strncmp(tmp->str, "<alt ", 5) || | |
| 302 !strncmp(tmp->str, "<snd ", 5)) { | |
| 6513 | 303 |
| 6629 | 304 /* remove this if gtkimhtml ever supports any of these */ |
| 6513 | 305 i = j; |
| 306 g_string_free(tmp, TRUE); | |
| 307 break; | |
| 308 | |
| 6629 | 309 } else if (!strncmp(tmp->str, "<font ", 6)) { |
| 310 _font_tags_fix_size(tmp, s); | |
| 6513 | 311 } else { |
| 8375 | 312 g_string_append(s, "<"); |
| 6513 | 313 g_string_free(tmp, TRUE); |
| 314 break; | |
| 315 } | |
| 316 | |
| 317 i = j; | |
| 318 g_string_free(tmp, TRUE); | |
| 319 break; | |
| 320 } | |
| 321 | |
| 322 } | |
| 323 | |
| 324 | |
| 325 | |
| 326 } else { | |
| 8375 | 327 if (x[i] == '<') |
| 328 g_string_append(s, "<"); | |
| 329 else if (x[i] == '>') | |
| 330 g_string_append(s, ">"); | |
| 8440 | 331 else if (x[i] == '&') |
| 332 g_string_append(s, "&"); | |
| 333 else if (x[i] == '"') | |
| 334 g_string_append(s, """); | |
| 8375 | 335 else |
| 336 g_string_append_c(s, x[i]); | |
| 6513 | 337 } |
| 338 } | |
| 339 | |
| 340 ret = s->str; | |
| 341 g_string_free(s, FALSE); | |
| 6629 | 342 gaim_debug(GAIM_DEBUG_MISC, "yahoo", "yahoo_codes_to_html: Returning string: '%s'.\n", ret); |
| 6513 | 343 return ret; |
| 344 } | |
| 6629 | 345 |
| 346 /* borrowed from gtkimhtml */ | |
| 347 #define MAX_FONT_SIZE 7 | |
| 348 #define POINT_SIZE(x) (_point_sizes [MIN ((x), MAX_FONT_SIZE) - 1]) | |
| 349 static gint _point_sizes [] = { 8, 10, 12, 14, 20, 30, 40 }; | |
| 350 | |
| 351 enum fatype { size, color, face, junk }; | |
| 352 typedef struct { | |
| 353 enum fatype type; | |
| 354 union { | |
| 355 int size; | |
| 356 char *color; | |
| 357 char *face; | |
| 358 char *junk; | |
| 359 } u; | |
| 360 } fontattr; | |
| 361 | |
| 362 static void fontattr_free(fontattr *f) | |
| 363 { | |
| 364 if (f->type == color) | |
| 365 g_free(f->u.color); | |
| 366 else if (f->type == face) | |
| 367 g_free(f->u.face); | |
| 368 g_free(f); | |
| 369 } | |
| 370 | |
| 371 static void yahoo_htc_queue_cleanup(GQueue *q) | |
| 372 { | |
| 373 char *tmp; | |
| 374 | |
| 375 while ((tmp = g_queue_pop_tail(q))) | |
| 376 g_free(tmp); | |
| 377 g_queue_free(q); | |
| 378 } | |
| 379 | |
| 380 static void _parse_font_tag(const char *src, GString *dest, int *i, int *j, | |
| 381 int len, GQueue *colors, GQueue *tags, GQueue *ftattr) | |
| 382 { | |
| 383 | |
| 384 int m, n, vstart; | |
| 385 gboolean quote = 0, done = 0; | |
| 386 | |
| 387 m = *j; | |
| 388 | |
| 389 while (1) { | |
| 390 m++; | |
| 391 | |
| 392 if (m >= len) { | |
| 393 g_string_append(dest, &src[*i]); | |
| 394 *i = len; | |
| 395 break; | |
| 396 } | |
| 397 | |
| 398 if (src[m] == '=') { | |
| 399 n = vstart = m; | |
| 400 while (1) { | |
| 401 n++; | |
| 402 | |
| 403 if (n >= len) { | |
| 404 m = n; | |
| 405 break; | |
| 406 } | |
| 407 | |
| 6631 | 408 if (src[n] == '"') { |
| 6629 | 409 if (!quote) { |
| 410 quote = 1; | |
| 411 vstart = n; | |
| 412 continue; | |
| 413 } else { | |
| 414 done = 1; | |
| 415 } | |
| 6631 | 416 } |
| 6629 | 417 |
| 418 if (!quote && ((src[n] == ' ') || (src[n] == '>'))) | |
| 419 done = 1; | |
| 420 | |
| 421 if (done) { | |
| 422 if (!g_ascii_strncasecmp(&src[*j+1], "FACE", m - *j - 1)) { | |
| 423 fontattr *f; | |
| 424 | |
| 425 f = g_new(fontattr, 1); | |
| 426 f->type = face; | |
| 427 f->u.face = g_strndup(&src[vstart+1], n-vstart-1); | |
| 428 if (!ftattr) | |
| 429 ftattr = g_queue_new(); | |
| 430 g_queue_push_tail(ftattr, f); | |
| 431 m = n; | |
| 432 break; | |
| 433 } else if (!g_ascii_strncasecmp(&src[*j+1], "SIZE", m - *j - 1)) { | |
| 434 fontattr *f; | |
| 435 | |
| 436 f = g_new(fontattr, 1); | |
| 437 f->type = size; | |
| 438 f->u.size = POINT_SIZE(strtol(&src[vstart+1], NULL, 10)); | |
| 439 if (!ftattr) | |
| 440 ftattr = g_queue_new(); | |
| 441 g_queue_push_tail(ftattr, f); | |
| 442 m = n; | |
| 443 break; | |
| 444 } else if (!g_ascii_strncasecmp(&src[*j+1], "COLOR", m - *j - 1)) { | |
| 445 fontattr *f; | |
| 446 | |
| 447 f = g_new(fontattr, 1); | |
| 448 f->type = color; | |
| 449 f->u.color = g_strndup(&src[vstart+1], n-vstart-1); | |
| 450 if (!ftattr) | |
| 451 ftattr = g_queue_new(); | |
| 452 g_queue_push_head(ftattr, f); | |
| 453 m = n; | |
| 454 break; | |
| 455 } else { | |
| 456 fontattr *f; | |
| 457 | |
| 458 f = g_new(fontattr, 1); | |
| 459 f->type = junk; | |
| 460 f->u.junk = g_strndup(&src[*j+1], n-*j); | |
| 461 if (!ftattr) | |
| 462 ftattr = g_queue_new(); | |
| 463 g_queue_push_tail(ftattr, f); | |
| 464 m = n; | |
| 465 break; | |
| 466 } | |
| 467 | |
| 468 } | |
| 469 } | |
| 470 } | |
| 471 | |
| 472 if (src[m] == ' ') | |
| 473 *j = m; | |
| 474 | |
| 475 | |
| 476 | |
| 477 if (src[m] == '>') { | |
| 478 gboolean needendtag = 0; | |
| 479 fontattr *f; | |
| 480 GString *tmp = g_string_new(NULL); | |
| 481 char *colorstr; | |
| 482 | |
| 483 if (!g_queue_is_empty(ftattr)) { | |
| 484 while ((f = g_queue_pop_tail(ftattr))) { | |
| 485 switch (f->type) { | |
| 486 case size: | |
| 487 if (!needendtag) { | |
| 488 needendtag = 1; | |
| 489 g_string_append(dest, "<font "); | |
| 490 } | |
| 491 | |
| 492 g_string_append_printf(dest, "size=\"%d\" ", f->u.size); | |
| 493 fontattr_free(f); | |
| 494 break; | |
| 495 case face: | |
| 496 if (!needendtag) { | |
| 497 needendtag = 1; | |
| 498 g_string_append(dest, "<font "); | |
| 499 } | |
| 500 | |
| 501 g_string_append_printf(dest, "face=\"%s\" ", f->u.face); | |
| 502 fontattr_free(f); | |
| 503 break; | |
| 504 case junk: | |
| 505 if (!needendtag) { | |
| 506 needendtag = 1; | |
| 507 g_string_append(dest, "<font "); | |
| 508 } | |
| 509 | |
| 510 g_string_append(dest, f->u.junk); | |
| 511 fontattr_free(f); | |
| 512 break; | |
| 513 | |
| 514 case color: | |
| 515 if (needendtag) { | |
| 516 g_string_append(tmp, "</font>"); | |
| 517 dest->str[dest->len-1] = '>'; | |
| 518 needendtag = 0; | |
| 519 } | |
| 520 | |
| 521 colorstr = g_queue_peek_tail(colors); | |
| 522 g_string_append(tmp, colorstr ? colorstr : "\033[#000000m"); | |
| 523 g_string_append_printf(dest, "\033[%sm", f->u.color); | |
| 524 g_queue_push_tail(colors, g_strdup_printf("\033[%sm", f->u.color)); | |
| 525 fontattr_free(f); | |
| 526 break; | |
| 527 } | |
| 528 } | |
| 529 | |
| 530 g_queue_free(ftattr); | |
| 531 ftattr = NULL; | |
| 532 | |
| 533 if (needendtag) { | |
| 534 dest->str[dest->len-1] = '>'; | |
| 535 g_queue_push_tail(tags, g_strdup("</font>")); | |
| 536 g_string_free(tmp, TRUE); | |
| 537 } else { | |
| 538 g_queue_push_tail(tags, tmp->str); | |
| 539 g_string_free(tmp, FALSE); | |
| 540 } | |
| 541 } | |
| 542 | |
| 543 *i = *j = m; | |
| 544 break; | |
| 545 } | |
| 546 } | |
| 547 | |
| 548 } | |
| 549 | |
| 550 char *yahoo_html_to_codes(const char *src) | |
| 551 { | |
| 6631 | 552 int i, j, len; |
| 6629 | 553 GString *dest; |
| 554 char *ret, *esc; | |
| 555 GQueue *colors, *tags; | |
| 556 GQueue *ftattr = NULL; | |
| 8440 | 557 gboolean no_more_specials = FALSE; |
| 6629 | 558 |
| 559 | |
| 560 colors = g_queue_new(); | |
| 561 tags = g_queue_new(); | |
| 562 | |
| 563 dest = g_string_sized_new(strlen(src)); | |
| 564 | |
| 565 for (i = 0, len = strlen(src); i < len; i++) { | |
| 566 | |
| 8440 | 567 if (!no_more_specials && src[i] == '<') { |
| 6629 | 568 j = i; |
| 569 | |
| 570 while (1) { | |
| 571 j++; | |
| 572 | |
| 573 if (j >= len) { /* no '>' */ | |
| 8440 | 574 g_string_append_c(dest, src[i]); |
| 575 no_more_specials = TRUE; | |
| 6629 | 576 break; |
| 577 } | |
| 578 | |
| 579 if (src[j] == '<') { | |
| 8440 | 580 /* FIXME: This doesn't convert outgoing entities. |
| 581 * However, I suspect this case may never | |
| 582 * happen anymore because of the entities. | |
| 583 */ | |
| 6629 | 584 g_string_append_len(dest, &src[i], j - i); |
| 585 i = j - 1; | |
| 586 if (ftattr) { | |
| 587 fontattr *f; | |
| 588 | |
| 589 while ((f = g_queue_pop_head(ftattr))) | |
| 590 fontattr_free(f); | |
| 591 g_queue_free(ftattr); | |
| 592 ftattr = NULL; | |
| 593 } | |
| 594 break; | |
| 595 } | |
| 596 | |
| 597 if (src[j] == ' ') { | |
| 598 if (!g_ascii_strncasecmp(&src[i+1], "BODY", j - i - 1)) { | |
| 599 char *t = strchr(&src[j], '>'); | |
| 600 if (!t) { | |
| 601 g_string_append(dest, &src[i]); | |
| 602 i = len; | |
| 603 break; | |
| 604 } else { | |
| 605 i = t - src; | |
| 606 break; | |
| 607 } | |
| 8533 | 608 } else if (!g_ascii_strncasecmp(&src[i+1], "A HREF=\"", j - i - 1)) { |
| 609 j += 7; | |
| 610 g_string_append(dest, "\033[lm"); | |
| 611 while (1) { | |
| 612 g_string_append_c(dest, src[j]); | |
| 613 if (++j >= len) { | |
| 8480 | 614 i = len; |
| 615 break; | |
| 616 } | |
| 8533 | 617 if (src[j] == '"') { |
| 618 g_string_append(dest, "\033[xlm"); | |
| 619 while (1) { | |
| 620 if (++j >= len) { | |
| 621 i = len; | |
| 622 break; | |
| 623 } | |
| 624 if (!g_ascii_strncasecmp(&src[j], "</A>", 4)) { | |
| 625 j += 3; | |
| 626 break; | |
| 627 } | |
| 628 } | |
| 629 i = j; | |
| 8480 | 630 break; |
| 631 } | |
| 632 } | |
| 6629 | 633 } else if (g_ascii_strncasecmp(&src[i+1], "FONT", j - i - 1)) { /* not interested! */ |
| 634 while (1) { | |
| 635 if (++j >= len) { | |
| 636 g_string_append(dest, &src[i]); | |
| 637 i = len; | |
| 638 break; | |
| 639 } | |
| 640 if (src[j] == '>') { | |
| 641 g_string_append_len(dest, &src[i], j - i + 1); | |
| 642 i = j; | |
| 643 break; | |
| 644 } | |
| 645 } | |
| 646 } else { /* yay we have a font tag */ | |
| 647 _parse_font_tag(src, dest, &i, &j, len, colors, tags, ftattr); | |
| 648 } | |
| 649 | |
| 650 break; | |
| 651 } | |
| 652 | |
| 653 if (src[j] == '>') { | |
| 8440 | 654 /* This has some problems like the FIXME for the |
| 655 * '<' case. and like that case, I suspect the case | |
| 656 * that this has problems is won't happen anymore anyway. | |
| 657 */ | |
| 6629 | 658 int sublen = j - i - 1; |
| 659 | |
| 660 if (sublen) { | |
| 661 if (!g_ascii_strncasecmp(&src[i+1], "B", sublen)) { | |
| 662 g_string_append(dest, "\033[1m"); | |
| 663 } else if (!g_ascii_strncasecmp(&src[i+1], "/B", sublen)) { | |
| 664 g_string_append(dest, "\033[x1m"); | |
| 665 } else if (!g_ascii_strncasecmp(&src[i+1], "I", sublen)) { | |
| 666 g_string_append(dest, "\033[2m"); | |
| 667 } else if (!g_ascii_strncasecmp(&src[i+1], "/I", sublen)) { | |
| 668 g_string_append(dest, "\033[x2m"); | |
| 669 } else if (!g_ascii_strncasecmp(&src[i+1], "U", sublen)) { | |
| 670 g_string_append(dest, "\033[4m"); | |
| 671 } else if (!g_ascii_strncasecmp(&src[i+1], "/U", sublen)) { | |
| 672 g_string_append(dest, "\033[x4m"); | |
| 8480 | 673 } else if (!g_ascii_strncasecmp(&src[i+1], "/A", sublen)) { |
| 674 g_string_append(dest, "\033[xlm"); | |
| 8455 | 675 } else if (!g_ascii_strncasecmp(&src[i+1], "BR", sublen)) { |
| 676 g_string_append_c(dest, '\n'); | |
| 6629 | 677 } else if (!g_ascii_strncasecmp(&src[i+1], "/BODY", sublen)) { |
| 678 /* mmm, </body> tags. *BURP* */ | |
| 679 } else if (!g_ascii_strncasecmp(&src[i+1], "/FONT", sublen) && g_queue_peek_tail(tags)) { | |
| 680 char *etag, *cl; | |
| 681 | |
| 682 etag = g_queue_pop_tail(tags); | |
| 683 if (etag) { | |
| 684 g_string_append(dest, etag); | |
| 685 if (!strcmp(etag, "</font>")) { | |
| 686 cl = g_queue_pop_tail(colors); | |
| 687 if (cl) | |
| 688 g_free(cl); | |
| 689 } | |
| 690 g_free(etag); | |
| 691 } | |
| 692 } else { | |
| 693 g_string_append_len(dest, &src[i], j - i + 1); | |
| 694 } | |
| 695 } else { | |
| 696 g_string_append_len(dest, &src[i], j - i + 1); | |
| 697 } | |
| 698 | |
| 699 i = j; | |
| 700 break; | |
| 701 } | |
| 702 | |
| 703 } | |
| 704 | |
| 705 } else { | |
| 8440 | 706 if (((len - i) >= 4) && !strncmp(&src[i], "<", 4)) { |
| 707 g_string_append_c(dest, '<'); | |
| 708 i += 3; | |
| 709 } else if (((len - i) >= 4) && !strncmp(&src[i], ">", 4)) { | |
| 710 g_string_append_c(dest, '>'); | |
| 711 i += 3; | |
| 712 } else if (((len - i) >= 5) && !strncmp(&src[i], "&", 4)) { | |
| 713 g_string_append_c(dest, '&'); | |
| 714 i += 4; | |
| 715 } else if (((len - i) >= 6) && !strncmp(&src[i], """, 4)) { | |
| 716 g_string_append_c(dest, '"'); | |
| 717 i += 5; | |
| 718 } else { | |
| 719 g_string_append_c(dest, src[i]); | |
| 720 } | |
| 6629 | 721 } |
| 722 } | |
| 723 | |
| 724 ret = dest->str; | |
| 725 g_string_free(dest, FALSE); | |
| 726 | |
| 727 esc = g_strescape(ret, NULL); | |
| 728 gaim_debug(GAIM_DEBUG_MISC, "yahoo", "yahoo_html_to_codes: Returning string: '%s'.\n", esc); | |
| 729 g_free(esc); | |
| 730 | |
| 731 yahoo_htc_queue_cleanup(colors); | |
| 732 yahoo_htc_queue_cleanup(tags); | |
| 733 | |
| 734 return ret; | |
| 735 } |
