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 }