libpurple/protocols/msnp9/msn-utils.c

branch
cpw.masca.webkit
changeset 32503
ab886d3a38ae
parent 32502
e64e49502c79
parent 31944
77d17906f1c3
child 32504
8243b910ed4c
equal deleted inserted replaced
32502:e64e49502c79 32503:ab886d3a38ae
1 /**
2 * @file msn-utils.c Utility functions
3 *
4 * purple
5 *
6 * Purple is the legal property of its developers, whose names are too numerous
7 * to list here. Please refer to the COPYRIGHT file distributed with this
8 * source distribution.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
23 */
24 #include "msn.h"
25 #include "msn-utils.h"
26
27 void
28 msn_parse_format(const char *mime, char **pre_ret, char **post_ret)
29 {
30 char *cur;
31 GString *pre = g_string_new(NULL);
32 GString *post = g_string_new(NULL);
33 unsigned int colors[3];
34
35 if (pre_ret != NULL) *pre_ret = NULL;
36 if (post_ret != NULL) *post_ret = NULL;
37
38 cur = strstr(mime, "FN=");
39
40 if (cur && (*(cur = cur + 3) != ';'))
41 {
42 pre = g_string_append(pre, "<FONT FACE=\"");
43
44 while (*cur && *cur != ';')
45 {
46 pre = g_string_append_c(pre, *cur);
47 cur++;
48 }
49
50 pre = g_string_append(pre, "\">");
51 post = g_string_prepend(post, "</FONT>");
52 }
53
54 cur = strstr(mime, "EF=");
55
56 if (cur && (*(cur = cur + 3) != ';'))
57 {
58 while (*cur && *cur != ';')
59 {
60 pre = g_string_append_c(pre, '<');
61 pre = g_string_append_c(pre, *cur);
62 pre = g_string_append_c(pre, '>');
63 post = g_string_prepend_c(post, '>');
64 post = g_string_prepend_c(post, *cur);
65 post = g_string_prepend_c(post, '/');
66 post = g_string_prepend_c(post, '<');
67 cur++;
68 }
69 }
70
71 cur = strstr(mime, "CO=");
72
73 if (cur && (*(cur = cur + 3) != ';'))
74 {
75 int i;
76
77 i = sscanf(cur, "%02x%02x%02x;", &colors[0], &colors[1], &colors[2]);
78
79 if (i > 0)
80 {
81 char tag[64];
82
83 if (i == 1)
84 {
85 colors[1] = 0;
86 colors[2] = 0;
87 }
88 else if (i == 2)
89 {
90 unsigned int temp = colors[0];
91
92 colors[0] = colors[1];
93 colors[1] = temp;
94 colors[2] = 0;
95 }
96 else if (i == 3)
97 {
98 unsigned int temp = colors[2];
99
100 colors[2] = colors[0];
101 colors[0] = temp;
102 }
103
104 g_snprintf(tag, sizeof(tag),
105 "<FONT COLOR=\"#%02hhx%02hhx%02hhx\">",
106 colors[0], colors[1], colors[2]);
107
108 pre = g_string_append(pre, tag);
109 post = g_string_prepend(post, "</FONT>");
110 }
111 }
112
113 cur = strstr(mime, "RL=");
114
115 if (cur && (*(cur = cur + 3) != ';'))
116 {
117 if (*cur == '1')
118 {
119 /* RTL text was received */
120 pre = g_string_append(pre, "<SPAN style=\"direction:rtl;text-align:right;\">");
121 post = g_string_prepend(post, "</SPAN>");
122 }
123 }
124
125 cur = g_strdup(purple_url_decode(pre->str));
126 g_string_free(pre, TRUE);
127
128 if (pre_ret != NULL)
129 *pre_ret = cur;
130 else
131 g_free(cur);
132
133 cur = g_strdup(purple_url_decode(post->str));
134 g_string_free(post, TRUE);
135
136 if (post_ret != NULL)
137 *post_ret = cur;
138 else
139 g_free(cur);
140 }
141
142 /*
143 * We need this because we're only supposed to encode spaces in the font
144 * names. purple_url_encode() isn't acceptable.
145 */
146 static const char *
147 encode_spaces(const char *str)
148 {
149 static char buf[BUF_LEN];
150 const char *c;
151 char *d;
152
153 g_return_val_if_fail(str != NULL, NULL);
154
155 for (c = str, d = buf; *c != '\0'; c++)
156 {
157 if (*c == ' ')
158 {
159 *d++ = '%';
160 *d++ = '2';
161 *d++ = '0';
162 }
163 else
164 *d++ = *c;
165 }
166 *d = '\0';
167
168 return buf;
169 }
170
171 /*
172 * Taken from the zephyr plugin.
173 * This parses HTML formatting (put out by one of the gtkimhtml widgets
174 * and converts it to msn formatting. It doesn't deal with the tag closing,
175 * but gtkimhtml widgets give valid html.
176 * It currently deals properly with <b>, <u>, <i>, <font face=...>,
177 * <font color=...>, <span dir=...>, <span style="direction: ...">.
178 * It ignores <font back=...> and <font size=...>
179 */
180 void
181 msn_import_html(const char *html, char **attributes, char **message)
182 {
183 int len, retcount = 0;
184 const char *c;
185 char *msg;
186 char *fontface = NULL;
187 char fonteffect[4];
188 char fontcolor[7];
189 char direction = '0';
190
191 gboolean has_bold = FALSE;
192 gboolean has_italic = FALSE;
193 gboolean has_underline = FALSE;
194 gboolean has_strikethrough = FALSE;
195
196 g_return_if_fail(html != NULL);
197 g_return_if_fail(attributes != NULL);
198 g_return_if_fail(message != NULL);
199
200 len = strlen(html);
201 msg = g_malloc0(len + 1);
202
203 memset(fontcolor, 0, sizeof(fontcolor));
204 strcat(fontcolor, "0");
205 memset(fonteffect, 0, sizeof(fonteffect));
206
207 for (c = html; *c != '\0';)
208 {
209 if (*c == '<')
210 {
211 if (!g_ascii_strncasecmp(c + 1, "br>", 3))
212 {
213 msg[retcount++] = '\r';
214 msg[retcount++] = '\n';
215 c += 4;
216 }
217 else if (!g_ascii_strncasecmp(c + 1, "i>", 2))
218 {
219 if (!has_italic)
220 {
221 strcat(fonteffect, "I");
222 has_italic = TRUE;
223 }
224 c += 3;
225 }
226 else if (!g_ascii_strncasecmp(c + 1, "b>", 2))
227 {
228 if (!has_bold)
229 {
230 strcat(fonteffect, "B");
231 has_bold = TRUE;
232 }
233 c += 3;
234 }
235 else if (!g_ascii_strncasecmp(c + 1, "u>", 2))
236 {
237 if (!has_underline)
238 {
239 strcat(fonteffect, "U");
240 has_underline = TRUE;
241 }
242 c += 3;
243 }
244 else if (!g_ascii_strncasecmp(c + 1, "s>", 2))
245 {
246 if (!has_strikethrough)
247 {
248 strcat(fonteffect, "S");
249 has_strikethrough = TRUE;
250 }
251 c += 3;
252 }
253 else if (!g_ascii_strncasecmp(c + 1, "a href=\"", 8))
254 {
255 c += 9;
256
257 if (!g_ascii_strncasecmp(c, "mailto:", 7))
258 c += 7;
259
260 while ((*c != '\0') && g_ascii_strncasecmp(c, "\">", 2))
261 msg[retcount++] = *c++;
262
263 if (*c != '\0')
264 c += 2;
265
266 /* ignore descriptive string */
267 while ((*c != '\0') && g_ascii_strncasecmp(c, "</a>", 4))
268 c++;
269
270 if (*c != '\0')
271 c += 4;
272 }
273 else if (!g_ascii_strncasecmp(c + 1, "span", 4))
274 {
275 /* Bi-directional text support using CSS properties in span tags */
276 c += 5;
277
278 while (*c != '\0' && *c != '>')
279 {
280 while (*c == ' ')
281 c++;
282 if (!g_ascii_strncasecmp(c, "dir=\"rtl\"", 9))
283 {
284 c += 9;
285 direction = '1';
286 }
287 else if (!g_ascii_strncasecmp(c, "style=\"", 7))
288 {
289 /* Parse inline CSS attributes */
290 char *attributes;
291 int attr_len = 0;
292 c += 7;
293 while (*(c + attr_len) != '\0' && *(c + attr_len) != '"')
294 attr_len++;
295 if (*(c + attr_len) == '"')
296 {
297 char *attr_dir;
298 attributes = g_strndup(c, attr_len);
299 attr_dir = purple_markup_get_css_property(attributes, "direction");
300 if (attr_dir && (!g_ascii_strncasecmp(attr_dir, "RTL", 3)))
301 direction = '1';
302 g_free(attr_dir);
303 g_free(attributes);
304 }
305
306 }
307 else
308 {
309 c++;
310 }
311 }
312 if (*c == '>')
313 c++;
314 }
315 else if (!g_ascii_strncasecmp(c + 1, "font", 4))
316 {
317 c += 5;
318
319 while ((*c != '\0') && !g_ascii_strncasecmp(c, " ", 1))
320 c++;
321
322 if (!g_ascii_strncasecmp(c, "color=\"#", 7))
323 {
324 c += 8;
325
326 fontcolor[0] = *(c + 4);
327 fontcolor[1] = *(c + 5);
328 fontcolor[2] = *(c + 2);
329 fontcolor[3] = *(c + 3);
330 fontcolor[4] = *c;
331 fontcolor[5] = *(c + 1);
332
333 c += 8;
334 }
335 else if (!g_ascii_strncasecmp(c, "face=\"", 6))
336 {
337 const char *end = NULL;
338 const char *comma = NULL;
339 unsigned int namelen = 0;
340
341 c += 6;
342 end = strchr(c, '\"');
343 comma = strchr(c, ',');
344
345 if (comma == NULL || comma > end)
346 namelen = (unsigned int)(end - c);
347 else
348 namelen = (unsigned int)(comma - c);
349
350 fontface = g_strndup(c, namelen);
351 c = end + 2;
352 }
353 else
354 {
355 /* Drop all unrecognized/misparsed font tags */
356 while ((*c != '\0') && g_ascii_strncasecmp(c, "\">", 2))
357 c++;
358
359 if (*c != '\0')
360 c += 2;
361 }
362 }
363 else
364 {
365 while ((*c != '\0') && (*c != '>'))
366 c++;
367 if (*c != '\0')
368 c++;
369 }
370 }
371 else if (*c == '&')
372 {
373 if (!g_ascii_strncasecmp(c, "&lt;", 4))
374 {
375 msg[retcount++] = '<';
376 c += 4;
377 }
378 else if (!g_ascii_strncasecmp(c, "&gt;", 4))
379 {
380 msg[retcount++] = '>';
381 c += 4;
382 }
383 else if (!g_ascii_strncasecmp(c, "&nbsp;", 6))
384 {
385 msg[retcount++] = ' ';
386 c += 6;
387 }
388 else if (!g_ascii_strncasecmp(c, "&quot;", 6))
389 {
390 msg[retcount++] = '"';
391 c += 6;
392 }
393 else if (!g_ascii_strncasecmp(c, "&amp;", 5))
394 {
395 msg[retcount++] = '&';
396 c += 5;
397 }
398 else if (!g_ascii_strncasecmp(c, "&apos;", 6))
399 {
400 msg[retcount++] = '\'';
401 c += 6;
402 }
403 else
404 msg[retcount++] = *c++;
405 }
406 else
407 msg[retcount++] = *c++;
408 }
409
410 if (fontface == NULL)
411 fontface = g_strdup("MS Sans Serif");
412
413 *attributes = g_strdup_printf("FN=%s; EF=%s; CO=%s; PF=0; RL=%c",
414 encode_spaces(fontface),
415 fonteffect, fontcolor, direction);
416 *message = g_strdup(msg);
417
418 g_free(fontface);
419 g_free(msg);
420 }
421
422 void
423 msn_parse_socket(const char *str, char **ret_host, int *ret_port)
424 {
425 char *host;
426 char *c;
427 int port;
428
429 host = g_strdup(str);
430
431 if ((c = strchr(host, ':')) != NULL)
432 {
433 *c = '\0';
434 port = atoi(c + 1);
435 }
436 else
437 port = 1863;
438
439 *ret_host = host;
440 *ret_port = port;
441 }

mercurial