| |
1 /** |
| |
2 * @file msn-utils.c Utility functions |
| |
3 * |
| |
4 * gaim |
| |
5 * |
| |
6 * Gaim 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 = g_strdup(gaim_url_decode(pre->str)); |
| |
114 g_string_free(pre, TRUE); |
| |
115 |
| |
116 if (pre_ret != NULL) |
| |
117 *pre_ret = cur; |
| |
118 else |
| |
119 g_free(cur); |
| |
120 |
| |
121 cur = g_strdup(gaim_url_decode(post->str)); |
| |
122 g_string_free(post, TRUE); |
| |
123 |
| |
124 if (post_ret != NULL) |
| |
125 *post_ret = cur; |
| |
126 else |
| |
127 g_free(cur); |
| |
128 } |
| |
129 |
| |
130 /* |
| |
131 * We need this because we're only supposed to encode spaces in the font |
| |
132 * names. gaim_url_encode() isn't acceptable. |
| |
133 */ |
| |
134 static const char * |
| |
135 encode_spaces(const char *str) |
| |
136 { |
| |
137 static char buf[BUF_LEN]; |
| |
138 const char *c; |
| |
139 char *d; |
| |
140 |
| |
141 g_return_val_if_fail(str != NULL, NULL); |
| |
142 |
| |
143 for (c = str, d = buf; *c != '\0'; c++) |
| |
144 { |
| |
145 if (*c == ' ') |
| |
146 { |
| |
147 *d++ = '%'; |
| |
148 *d++ = '2'; |
| |
149 *d++ = '0'; |
| |
150 } |
| |
151 else |
| |
152 *d++ = *c; |
| |
153 } |
| |
154 |
| |
155 return buf; |
| |
156 } |
| |
157 |
| |
158 /* |
| |
159 * Taken from the zephyr plugin. |
| |
160 * This parses HTML formatting (put out by one of the gtkimhtml widgets |
| |
161 * and converts it to msn formatting. It doesn't deal with the tag closing, |
| |
162 * but gtkimhtml widgets give valid html. |
| |
163 * It currently deals properly with <b>, <u>, <i>, <font face=...>, |
| |
164 * <font color=...>. |
| |
165 * It ignores <font back=...> and <font size=...> |
| |
166 */ |
| |
167 void |
| |
168 msn_import_html(const char *html, char **attributes, char **message) |
| |
169 { |
| |
170 int len, retcount = 0; |
| |
171 const char *c; |
| |
172 char *msg; |
| |
173 char *fontface = NULL; |
| |
174 char fonteffect[4]; |
| |
175 char fontcolor[7]; |
| |
176 |
| |
177 g_return_if_fail(html != NULL); |
| |
178 g_return_if_fail(attributes != NULL); |
| |
179 g_return_if_fail(message != NULL); |
| |
180 |
| |
181 len = strlen(html); |
| |
182 msg = g_malloc0(len + 1); |
| |
183 |
| |
184 memset(fontcolor, 0, sizeof(fontcolor)); |
| |
185 strcat(fontcolor, "0"); |
| |
186 memset(fonteffect, 0, sizeof(fonteffect)); |
| |
187 |
| |
188 for (c = html; *c != '\0';) |
| |
189 { |
| |
190 if (*c == '<') |
| |
191 { |
| |
192 if (!g_ascii_strncasecmp(c + 1, "br>", 3)) |
| |
193 { |
| |
194 msg[retcount++] = '\r'; |
| |
195 msg[retcount++] = '\n'; |
| |
196 c += 4; |
| |
197 } |
| |
198 else if (!g_ascii_strncasecmp(c + 1, "i>", 2)) |
| |
199 { |
| |
200 strcat(fonteffect, "I"); |
| |
201 c += 3; |
| |
202 } |
| |
203 else if (!g_ascii_strncasecmp(c + 1, "b>", 2)) |
| |
204 { |
| |
205 strcat(fonteffect, "B"); |
| |
206 c += 3; |
| |
207 } |
| |
208 else if (!g_ascii_strncasecmp(c + 1, "u>", 2)) |
| |
209 { |
| |
210 strcat(fonteffect, "U"); |
| |
211 c += 3; |
| |
212 } |
| |
213 else if (!g_ascii_strncasecmp(c + 1, "s>", 2)) |
| |
214 { |
| |
215 strcat(fonteffect, "S"); |
| |
216 c += 3; |
| |
217 } |
| |
218 else if (!g_ascii_strncasecmp(c + 1, "a href=\"", 8)) |
| |
219 { |
| |
220 c += 9; |
| |
221 |
| |
222 if (!g_ascii_strncasecmp(c, "mailto:", 7)) |
| |
223 c += 7; |
| |
224 |
| |
225 while ((*c != '\0') && g_ascii_strncasecmp(c, "\">", 2)) |
| |
226 msg[retcount++] = *c++; |
| |
227 |
| |
228 if (*c != '\0') |
| |
229 c += 2; |
| |
230 |
| |
231 /* ignore descriptive string */ |
| |
232 while ((*c != '\0') && g_ascii_strncasecmp(c, "</a>", 4)) |
| |
233 c++; |
| |
234 |
| |
235 if (*c != '\0') |
| |
236 c += 4; |
| |
237 } |
| |
238 else if (!g_ascii_strncasecmp(c + 1, "font", 4)) |
| |
239 { |
| |
240 c += 5; |
| |
241 |
| |
242 while ((*c != '\0') && !g_ascii_strncasecmp(c, " ", 1)) |
| |
243 c++; |
| |
244 |
| |
245 if (!g_ascii_strncasecmp(c, "color=\"#", 7)) |
| |
246 { |
| |
247 c += 8; |
| |
248 |
| |
249 fontcolor[0] = *(c + 4); |
| |
250 fontcolor[1] = *(c + 5); |
| |
251 fontcolor[2] = *(c + 2); |
| |
252 fontcolor[3] = *(c + 3); |
| |
253 fontcolor[4] = *c; |
| |
254 fontcolor[5] = *(c + 1); |
| |
255 |
| |
256 c += 8; |
| |
257 } |
| |
258 else if (!g_ascii_strncasecmp(c, "face=\"", 6)) |
| |
259 { |
| |
260 const char *end = NULL; |
| |
261 const char *comma = NULL; |
| |
262 unsigned int namelen = 0; |
| |
263 |
| |
264 c += 6; |
| |
265 end = strchr(c, '\"'); |
| |
266 comma = strchr(c, ','); |
| |
267 |
| |
268 if (comma == NULL || comma > end) |
| |
269 namelen = (unsigned int)(end - c); |
| |
270 else |
| |
271 namelen = (unsigned int)(comma - c); |
| |
272 |
| |
273 fontface = g_strndup(c, namelen); |
| |
274 c = end + 2; |
| |
275 } |
| |
276 else |
| |
277 { |
| |
278 /* Drop all unrecognized/misparsed font tags */ |
| |
279 while ((*c != '\0') && g_ascii_strncasecmp(c, "\">", 2)) |
| |
280 c++; |
| |
281 |
| |
282 if (*c != '\0') |
| |
283 c += 2; |
| |
284 } |
| |
285 } |
| |
286 else |
| |
287 { |
| |
288 while ((*c != '\0') && (*c != '>')) |
| |
289 c++; |
| |
290 if (*c != '\0') |
| |
291 c++; |
| |
292 } |
| |
293 } |
| |
294 else if (*c == '&') |
| |
295 { |
| |
296 if (!g_ascii_strncasecmp(c, "<", 4)) |
| |
297 { |
| |
298 msg[retcount++] = '<'; |
| |
299 c += 4; |
| |
300 } |
| |
301 else if (!g_ascii_strncasecmp(c, ">", 4)) |
| |
302 { |
| |
303 msg[retcount++] = '>'; |
| |
304 c += 4; |
| |
305 } |
| |
306 else if (!g_ascii_strncasecmp(c, " ", 6)) |
| |
307 { |
| |
308 msg[retcount++] = ' '; |
| |
309 c += 6; |
| |
310 } |
| |
311 else if (!g_ascii_strncasecmp(c, """, 6)) |
| |
312 { |
| |
313 msg[retcount++] = '"'; |
| |
314 c += 6; |
| |
315 } |
| |
316 else if (!g_ascii_strncasecmp(c, "&", 5)) |
| |
317 { |
| |
318 msg[retcount++] = '&'; |
| |
319 c += 5; |
| |
320 } |
| |
321 else if (!g_ascii_strncasecmp(c, "'", 6)) |
| |
322 { |
| |
323 msg[retcount++] = '\''; |
| |
324 c += 6; |
| |
325 } |
| |
326 else |
| |
327 msg[retcount++] = *c++; |
| |
328 } |
| |
329 else |
| |
330 msg[retcount++] = *c++; |
| |
331 } |
| |
332 |
| |
333 if (fontface == NULL) |
| |
334 fontface = g_strdup("MS Sans Serif"); |
| |
335 |
| |
336 *attributes = g_strdup_printf("FN=%s; EF=%s; CO=%s; PF=0", |
| |
337 encode_spaces(fontface), |
| |
338 fonteffect, fontcolor); |
| |
339 *message = g_strdup(msg); |
| |
340 |
| |
341 g_free(fontface); |
| |
342 g_free(msg); |
| |
343 } |
| |
344 |
| |
345 void |
| |
346 msn_parse_socket(const char *str, char **ret_host, int *ret_port) |
| |
347 { |
| |
348 char *host; |
| |
349 char *c; |
| |
350 int port; |
| |
351 |
| |
352 host = g_strdup(str); |
| |
353 |
| |
354 if ((c = strchr(host, ':')) != NULL) |
| |
355 { |
| |
356 *c = '\0'; |
| |
357 port = atoi(c + 1); |
| |
358 } |
| |
359 else |
| |
360 port = 1863; |
| |
361 |
| |
362 *ret_host = host; |
| |
363 *ret_port = port; |
| |
364 } |