Mercurial > pidgin
comparison src/protocols/yahoo/util.c @ 6629:bdc448cf4cb6
[gaim-migrate @ 7153]
Tim Ringenbach (marv_sf) writes:
" This patch makes sending colors in yahoo work. It also
makes a few changing to receiving them, and addresses
most of the problems with that patch (which I think
were all related to the fact it didn't do outgoing colors).
It now handles bold, italic, underline, font face, font
size, and font color in both directions. It disables
the background color button if the prpl is yahoo (in a
generic way), and farthermore strips out any <body>
tags that the user might try to type anyway (the yahoo
server purposely mangles them).
It also adds a line to g_strescape some debug messages
because I got tired them of changing the color of my
terminal.
I think I got all the bugs out. If you run with -d or
open the debug window, it will show you what both
conversion function returned, which should help track
down any problems."
committer: Tailor Script <tailor@pidgin.im>
author | Luke Schierer <lschiere@pidgin.im> |
---|---|
date | Tue, 26 Aug 2003 01:34:51 +0000 |
parents | 42fdf16f1dad |
children | f80e23e66de0 |
comparison
equal
deleted
inserted
replaced
6628:31b39f6c2142 | 6629:bdc448cf4cb6 |
---|---|
57 static GHashTable *ht = NULL; | 57 static GHashTable *ht = NULL; |
58 | 58 |
59 void yahoo_init_colorht() | 59 void yahoo_init_colorht() |
60 { | 60 { |
61 ht = g_hash_table_new(g_str_hash, g_str_equal); | 61 ht = g_hash_table_new(g_str_hash, g_str_equal); |
62 | 62 /* the numbers in comments are what gyach uses, but i think they're incorrect */ |
63 g_hash_table_insert(ht, "30", "<FONT COLOR=\"#000000\">"); /* black */ | 63 g_hash_table_insert(ht, "30", "<FONT COLOR=\"#000000\">"); /* black */ |
64 g_hash_table_insert(ht, "31", "<FONT COLOR=\"#0000FF\">"); /* blue */ | 64 g_hash_table_insert(ht, "31", "<FONT COLOR=\"#0000FF\">"); /* blue */ |
65 g_hash_table_insert(ht, "32", "<FONT COLOR=\"#008080\">"); /* cyan */ /* 00b2b2 */ | 65 g_hash_table_insert(ht, "32", "<FONT COLOR=\"#008080\">"); /* cyan */ /* 00b2b2 */ |
66 g_hash_table_insert(ht, "33", "<FONT COLOR=\"#808080\">"); /* gray */ /* 808080 */ | 66 g_hash_table_insert(ht, "33", "<FONT COLOR=\"#808080\">"); /* gray */ /* 808080 */ |
67 g_hash_table_insert(ht, "34", "<FONT COLOR=\"#008000\">"); /* green */ /* 00c200 */ | 67 g_hash_table_insert(ht, "34", "<FONT COLOR=\"#008000\">"); /* green */ /* 00c200 */ |
76 g_hash_table_insert(ht, "2", "<I>"); | 76 g_hash_table_insert(ht, "2", "<I>"); |
77 g_hash_table_insert(ht, "x2", "</I>"); | 77 g_hash_table_insert(ht, "x2", "</I>"); |
78 g_hash_table_insert(ht, "4", "<U>"); | 78 g_hash_table_insert(ht, "4", "<U>"); |
79 g_hash_table_insert(ht, "x4", "</U>"); | 79 g_hash_table_insert(ht, "x4", "</U>"); |
80 | 80 |
81 /* these just tell us the text they surround is supposed | |
82 * to be a link. gaim figures that out on its own so we | |
83 * just ignore it. | |
84 */ | |
85 g_hash_table_insert(ht, "l", ""); /* link start */ | |
86 g_hash_table_insert(ht, "xl", ""); /* link end */ | |
87 | |
88 | |
81 g_hash_table_insert(ht, "<black>", "<FONT COLOR=\"#000000\">"); | 89 g_hash_table_insert(ht, "<black>", "<FONT COLOR=\"#000000\">"); |
82 g_hash_table_insert(ht, "<blue>", "<FONT COLOR=\"#0000FF\">"); | 90 g_hash_table_insert(ht, "<blue>", "<FONT COLOR=\"#0000FF\">"); |
83 g_hash_table_insert(ht, "<cyan>", "<FONT COLOR=\"#008284\">"); | 91 g_hash_table_insert(ht, "<cyan>", "<FONT COLOR=\"#008284\">"); |
84 g_hash_table_insert(ht, "<gray>", "<FONT COLOR=\"#848284\">"); | 92 g_hash_table_insert(ht, "<gray>", "<FONT COLOR=\"#848284\">"); |
85 g_hash_table_insert(ht, "<green>", "<FONT COLOR=\"#008200\">"); | 93 g_hash_table_insert(ht, "<green>", "<FONT COLOR=\"#008200\">"); |
108 void yahoo_dest_colorht() | 116 void yahoo_dest_colorht() |
109 { | 117 { |
110 g_hash_table_destroy(ht); | 118 g_hash_table_destroy(ht); |
111 } | 119 } |
112 | 120 |
113 char *yahoo_codes_to_html(char *x) | 121 static int point_to_html(int x) |
122 { | |
123 if (x < 9) | |
124 return 1; | |
125 if (x < 11) | |
126 return 2; | |
127 if (x < 13) | |
128 return 3; | |
129 if (x < 17) | |
130 return 4; | |
131 if (x < 25) | |
132 return 5; | |
133 if (x < 35) | |
134 return 6; | |
135 return 7; | |
136 } | |
137 static void _font_tags_fix_size(GString *tag, GString *dest) | |
138 { | |
139 char *x, *end; | |
140 int size; | |
141 | |
142 if (((x = strstr(tag->str, "size"))) && ((x = strchr(tag->str, '=')))) { | |
143 while (*x && !g_ascii_isdigit(*x)) | |
144 x++; | |
145 if (*x) { | |
146 size = strtol(x, &end, 10); | |
147 size = point_to_html(size); | |
148 g_string_append_len(dest, tag->str, x - tag->str); | |
149 g_string_append_printf(dest, "%d", size); | |
150 g_string_append(dest, end); | |
151 } else { | |
152 g_string_append(dest, tag->str); | |
153 return; | |
154 } | |
155 } else { | |
156 g_string_append(dest, tag->str); | |
157 return; | |
158 } | |
159 } | |
160 | |
161 char *yahoo_codes_to_html(const char *x) | |
114 { | 162 { |
115 GString *s, *tmp; | 163 GString *s, *tmp; |
116 int i, j, xs, nomoreendtags = 0; | 164 int i, j, xs, nomoreendtags = 0; /* s/endtags/closinganglebrackets */ |
117 char *match, *ret; | 165 char *match, *ret; |
118 | 166 |
119 | 167 |
120 s = g_string_sized_new(strlen(x)); | 168 s = g_string_sized_new(strlen(x)); |
121 | 169 |
145 } | 193 } |
146 } | 194 } |
147 | 195 |
148 | 196 |
149 } else if (!nomoreendtags && (x[i] == '<')) { | 197 } else if (!nomoreendtags && (x[i] == '<')) { |
150 j = i + 1; | 198 j = i; |
151 | 199 |
152 while (j++ < xs) { | 200 while (j++ < xs) { |
153 if (x[j] != '>') | 201 if (x[j] != '>') |
154 if (j == xs) { | 202 if (j == xs) { |
155 g_string_append_c(s, '<'); | 203 g_string_append_c(s, '<'); |
161 tmp = g_string_new_len(x + i, j - i + 1); | 209 tmp = g_string_new_len(x + i, j - i + 1); |
162 g_string_ascii_down(tmp); | 210 g_string_ascii_down(tmp); |
163 | 211 |
164 if ((match = (char *) g_hash_table_lookup(ht, tmp->str))) | 212 if ((match = (char *) g_hash_table_lookup(ht, tmp->str))) |
165 g_string_append(s, match); | 213 g_string_append(s, match); |
166 else if (!g_ascii_strncasecmp(tmp->str, "<FADE ", 6) || | 214 else if (!strncmp(tmp->str, "<fade ", 6) || |
167 !g_ascii_strncasecmp(tmp->str, "<ALT ", 5) || | 215 !strncmp(tmp->str, "<alt ", 5) || |
168 !g_ascii_strncasecmp(tmp->str, "<SND ", 5)) { | 216 !strncmp(tmp->str, "<snd ", 5)) { |
169 | 217 |
170 /* remove this if gtkhtml ever supports any of these */ | 218 /* remove this if gtkimhtml ever supports any of these */ |
171 i = j; | 219 i = j; |
172 g_string_free(tmp, TRUE); | 220 g_string_free(tmp, TRUE); |
173 break; | 221 break; |
174 | 222 |
223 } else if (!strncmp(tmp->str, "<font ", 6)) { | |
224 _font_tags_fix_size(tmp, s); | |
175 } else { | 225 } else { |
176 g_string_append_c(s, '<'); | 226 g_string_append_c(s, '<'); |
177 g_string_free(tmp, TRUE); | 227 g_string_free(tmp, TRUE); |
178 break; | 228 break; |
179 } | 229 } |
192 } | 242 } |
193 } | 243 } |
194 | 244 |
195 ret = s->str; | 245 ret = s->str; |
196 g_string_free(s, FALSE); | 246 g_string_free(s, FALSE); |
197 gaim_debug(GAIM_DEBUG_MISC, "yahoo", "Returning string: '%s'.\n", ret); | 247 gaim_debug(GAIM_DEBUG_MISC, "yahoo", "yahoo_codes_to_html: Returning string: '%s'.\n", ret); |
198 return ret; | 248 return ret; |
199 } | 249 } |
250 | |
251 /* borrowed from gtkimhtml */ | |
252 #define MAX_FONT_SIZE 7 | |
253 #define POINT_SIZE(x) (_point_sizes [MIN ((x), MAX_FONT_SIZE) - 1]) | |
254 static gint _point_sizes [] = { 8, 10, 12, 14, 20, 30, 40 }; | |
255 | |
256 enum fatype { size, color, face, junk }; | |
257 typedef struct { | |
258 enum fatype type; | |
259 union { | |
260 int size; | |
261 char *color; | |
262 char *face; | |
263 char *junk; | |
264 } u; | |
265 } fontattr; | |
266 | |
267 static void fontattr_free(fontattr *f) | |
268 { | |
269 if (f->type == color) | |
270 g_free(f->u.color); | |
271 else if (f->type == face) | |
272 g_free(f->u.face); | |
273 g_free(f); | |
274 } | |
275 | |
276 static void yahoo_htc_queue_cleanup(GQueue *q) | |
277 { | |
278 char *tmp; | |
279 | |
280 while ((tmp = g_queue_pop_tail(q))) | |
281 g_free(tmp); | |
282 g_queue_free(q); | |
283 } | |
284 | |
285 static void _parse_font_tag(const char *src, GString *dest, int *i, int *j, | |
286 int len, GQueue *colors, GQueue *tags, GQueue *ftattr) | |
287 { | |
288 | |
289 int m, n, vstart; | |
290 gboolean quote = 0, done = 0; | |
291 | |
292 m = *j; | |
293 | |
294 while (1) { | |
295 m++; | |
296 | |
297 if (m >= len) { | |
298 g_string_append(dest, &src[*i]); | |
299 *i = len; | |
300 break; | |
301 } | |
302 | |
303 if (src[m] == '=') { | |
304 n = vstart = m; | |
305 while (1) { | |
306 n++; | |
307 | |
308 if (n >= len) { | |
309 m = n; | |
310 break; | |
311 } | |
312 | |
313 if (src[n] == '"') | |
314 if (!quote) { | |
315 quote = 1; | |
316 vstart = n; | |
317 continue; | |
318 } else { | |
319 done = 1; | |
320 } | |
321 | |
322 if (!quote && ((src[n] == ' ') || (src[n] == '>'))) | |
323 done = 1; | |
324 | |
325 if (done) { | |
326 if (!g_ascii_strncasecmp(&src[*j+1], "FACE", m - *j - 1)) { | |
327 fontattr *f; | |
328 | |
329 f = g_new(fontattr, 1); | |
330 f->type = face; | |
331 f->u.face = g_strndup(&src[vstart+1], n-vstart-1); | |
332 if (!ftattr) | |
333 ftattr = g_queue_new(); | |
334 g_queue_push_tail(ftattr, f); | |
335 m = n; | |
336 break; | |
337 } else if (!g_ascii_strncasecmp(&src[*j+1], "SIZE", m - *j - 1)) { | |
338 fontattr *f; | |
339 | |
340 f = g_new(fontattr, 1); | |
341 f->type = size; | |
342 f->u.size = POINT_SIZE(strtol(&src[vstart+1], NULL, 10)); | |
343 if (!ftattr) | |
344 ftattr = g_queue_new(); | |
345 g_queue_push_tail(ftattr, f); | |
346 m = n; | |
347 break; | |
348 } else if (!g_ascii_strncasecmp(&src[*j+1], "COLOR", m - *j - 1)) { | |
349 fontattr *f; | |
350 | |
351 f = g_new(fontattr, 1); | |
352 f->type = color; | |
353 f->u.color = g_strndup(&src[vstart+1], n-vstart-1); | |
354 if (!ftattr) | |
355 ftattr = g_queue_new(); | |
356 g_queue_push_head(ftattr, f); | |
357 m = n; | |
358 break; | |
359 } else { | |
360 fontattr *f; | |
361 | |
362 f = g_new(fontattr, 1); | |
363 f->type = junk; | |
364 f->u.junk = g_strndup(&src[*j+1], n-*j); | |
365 if (!ftattr) | |
366 ftattr = g_queue_new(); | |
367 g_queue_push_tail(ftattr, f); | |
368 m = n; | |
369 break; | |
370 } | |
371 | |
372 } | |
373 } | |
374 } | |
375 | |
376 if (src[m] == ' ') | |
377 *j = m; | |
378 | |
379 | |
380 | |
381 if (src[m] == '>') { | |
382 gboolean needendtag = 0; | |
383 fontattr *f; | |
384 GString *tmp = g_string_new(NULL); | |
385 char *colorstr; | |
386 | |
387 if (!g_queue_is_empty(ftattr)) { | |
388 while ((f = g_queue_pop_tail(ftattr))) { | |
389 switch (f->type) { | |
390 case size: | |
391 if (!needendtag) { | |
392 needendtag = 1; | |
393 g_string_append(dest, "<font "); | |
394 } | |
395 | |
396 g_string_append_printf(dest, "size=\"%d\" ", f->u.size); | |
397 fontattr_free(f); | |
398 break; | |
399 case face: | |
400 if (!needendtag) { | |
401 needendtag = 1; | |
402 g_string_append(dest, "<font "); | |
403 } | |
404 | |
405 g_string_append_printf(dest, "face=\"%s\" ", f->u.face); | |
406 fontattr_free(f); | |
407 break; | |
408 case junk: | |
409 if (!needendtag) { | |
410 needendtag = 1; | |
411 g_string_append(dest, "<font "); | |
412 } | |
413 | |
414 g_string_append(dest, f->u.junk); | |
415 fontattr_free(f); | |
416 break; | |
417 | |
418 case color: | |
419 if (needendtag) { | |
420 g_string_append(tmp, "</font>"); | |
421 dest->str[dest->len-1] = '>'; | |
422 needendtag = 0; | |
423 } | |
424 | |
425 colorstr = g_queue_peek_tail(colors); | |
426 g_string_append(tmp, colorstr ? colorstr : "\033[#000000m"); | |
427 g_string_append_printf(dest, "\033[%sm", f->u.color); | |
428 g_queue_push_tail(colors, g_strdup_printf("\033[%sm", f->u.color)); | |
429 fontattr_free(f); | |
430 break; | |
431 } | |
432 } | |
433 | |
434 g_queue_free(ftattr); | |
435 ftattr = NULL; | |
436 | |
437 if (needendtag) { | |
438 dest->str[dest->len-1] = '>'; | |
439 g_queue_push_tail(tags, g_strdup("</font>")); | |
440 g_string_free(tmp, TRUE); | |
441 } else { | |
442 g_queue_push_tail(tags, tmp->str); | |
443 g_string_free(tmp, FALSE); | |
444 } | |
445 } | |
446 | |
447 *i = *j = m; | |
448 break; | |
449 } | |
450 } | |
451 | |
452 } | |
453 | |
454 char *yahoo_html_to_codes(const char *src) | |
455 { | |
456 int i, j, m, n, vstart, len; | |
457 GString *dest; | |
458 char *ret, *esc; | |
459 GQueue *colors, *tags; | |
460 GQueue *ftattr = NULL; | |
461 | |
462 | |
463 colors = g_queue_new(); | |
464 tags = g_queue_new(); | |
465 | |
466 dest = g_string_sized_new(strlen(src)); | |
467 | |
468 for (i = 0, len = strlen(src); i < len; i++) { | |
469 | |
470 if (src[i] == '<') { | |
471 j = i; | |
472 | |
473 while (1) { | |
474 j++; | |
475 | |
476 if (j >= len) { /* no '>' */ | |
477 g_string_append_len(dest, &src[i], len - i); | |
478 i = len; | |
479 | |
480 break; | |
481 } | |
482 | |
483 if (src[j] == '<') { | |
484 g_string_append_len(dest, &src[i], j - i); | |
485 i = j - 1; | |
486 if (ftattr) { | |
487 fontattr *f; | |
488 | |
489 while ((f = g_queue_pop_head(ftattr))) | |
490 fontattr_free(f); | |
491 g_queue_free(ftattr); | |
492 ftattr = NULL; | |
493 } | |
494 break; | |
495 } | |
496 | |
497 if (src[j] == ' ') { | |
498 if (!g_ascii_strncasecmp(&src[i+1], "BODY", j - i - 1)) { | |
499 char *t = strchr(&src[j], '>'); | |
500 if (!t) { | |
501 g_string_append(dest, &src[i]); | |
502 i = len; | |
503 break; | |
504 } else { | |
505 i = t - src; | |
506 break; | |
507 } | |
508 } else if (g_ascii_strncasecmp(&src[i+1], "FONT", j - i - 1)) { /* not interested! */ | |
509 while (1) { | |
510 if (++j >= len) { | |
511 g_string_append(dest, &src[i]); | |
512 i = len; | |
513 break; | |
514 } | |
515 if (src[j] == '>') { | |
516 g_string_append_len(dest, &src[i], j - i + 1); | |
517 i = j; | |
518 break; | |
519 } | |
520 } | |
521 } else { /* yay we have a font tag */ | |
522 _parse_font_tag(src, dest, &i, &j, len, colors, tags, ftattr); | |
523 } | |
524 | |
525 break; | |
526 } | |
527 | |
528 if (src[j] == '>') { | |
529 int sublen = j - i - 1; | |
530 | |
531 if (sublen) { | |
532 if (!g_ascii_strncasecmp(&src[i+1], "B", sublen)) { | |
533 g_string_append(dest, "\033[1m"); | |
534 } else if (!g_ascii_strncasecmp(&src[i+1], "/B", sublen)) { | |
535 g_string_append(dest, "\033[x1m"); | |
536 } else if (!g_ascii_strncasecmp(&src[i+1], "I", sublen)) { | |
537 g_string_append(dest, "\033[2m"); | |
538 } else if (!g_ascii_strncasecmp(&src[i+1], "/I", sublen)) { | |
539 g_string_append(dest, "\033[x2m"); | |
540 } else if (!g_ascii_strncasecmp(&src[i+1], "U", sublen)) { | |
541 g_string_append(dest, "\033[4m"); | |
542 } else if (!g_ascii_strncasecmp(&src[i+1], "/U", sublen)) { | |
543 g_string_append(dest, "\033[x4m"); | |
544 } else if (!g_ascii_strncasecmp(&src[i+1], "/BODY", sublen)) { | |
545 /* mmm, </body> tags. *BURP* */ | |
546 } else if (!g_ascii_strncasecmp(&src[i+1], "/FONT", sublen) && g_queue_peek_tail(tags)) { | |
547 char *etag, *cl; | |
548 | |
549 etag = g_queue_pop_tail(tags); | |
550 if (etag) { | |
551 g_string_append(dest, etag); | |
552 if (!strcmp(etag, "</font>")) { | |
553 cl = g_queue_pop_tail(colors); | |
554 if (cl) | |
555 g_free(cl); | |
556 } | |
557 g_free(etag); | |
558 } | |
559 } else { | |
560 g_string_append_len(dest, &src[i], j - i + 1); | |
561 } | |
562 } else { | |
563 g_string_append_len(dest, &src[i], j - i + 1); | |
564 } | |
565 | |
566 i = j; | |
567 break; | |
568 } | |
569 | |
570 } | |
571 | |
572 } else { | |
573 g_string_append_c(dest, src[i]); | |
574 } | |
575 } | |
576 | |
577 ret = dest->str; | |
578 g_string_free(dest, FALSE); | |
579 | |
580 esc = g_strescape(ret, NULL); | |
581 gaim_debug(GAIM_DEBUG_MISC, "yahoo", "yahoo_html_to_codes: Returning string: '%s'.\n", esc); | |
582 g_free(esc); | |
583 | |
584 yahoo_htc_queue_cleanup(colors); | |
585 yahoo_htc_queue_cleanup(tags); | |
586 | |
587 return ret; | |
588 } |