comparison libpurple/protocols/silc/util.c @ 15373:5fe8042783c1

Rename gtk/ and libgaim/ to pidgin/ and libpurple/
author Sean Egan <seanegan@gmail.com>
date Sat, 20 Jan 2007 02:32:10 +0000
parents
children 32c366eeeb99
comparison
equal deleted inserted replaced
15372:f79e0f4df793 15373:5fe8042783c1
1 /*
2
3 silcgaim_util.c
4
5 Author: Pekka Riikonen <priikone@silcnet.org>
6
7 Copyright (C) 2004 - 2005 Pekka Riikonen
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 */
19
20 #include "silcincludes.h"
21 #include "silcclient.h"
22 #include "silcgaim.h"
23 #include "imgstore.h"
24
25 /**************************** Utility Routines *******************************/
26
27 static char str[256], str2[256];
28
29 const char *silcgaim_silcdir(void)
30 {
31 const char *hd = gaim_home_dir();
32 memset(str, 0, sizeof(str));
33 g_snprintf(str, sizeof(str) - 1, "%s" G_DIR_SEPARATOR_S ".silc", hd ? hd : "/tmp");
34 return (const char *)str;
35 }
36
37 const char *silcgaim_session_file(const char *account)
38 {
39 memset(str2, 0, sizeof(str2));
40 g_snprintf(str2, sizeof(str2) - 1, "%s" G_DIR_SEPARATOR_S "%s_session",
41 silcgaim_silcdir(), account);
42 return (const char *)str2;
43 }
44
45 gboolean silcgaim_ip_is_private(const char *ip)
46 {
47 if (silc_net_is_ip4(ip)) {
48 if (!strncmp(ip, "10.", 3)) {
49 return TRUE;
50 } else if (!strncmp(ip, "172.", 4) && strlen(ip) > 6) {
51 char tmp[3];
52 int s;
53 memset(tmp, 0, sizeof(tmp));
54 strncpy(tmp, ip + 4, 2);
55 s = atoi(tmp);
56 if (s >= 16 && s <= 31)
57 return TRUE;
58 } else if (!strncmp(ip, "192.168.", 8)) {
59 return TRUE;
60 }
61 }
62
63 return FALSE;
64 }
65
66 /* This checks stats for various SILC files and directories. First it
67 checks if ~/.silc directory exist and is owned by the correct user. If
68 it doesn't exist, it will create the directory. After that it checks if
69 user's Public and Private key files exists and creates them if needed. */
70
71 gboolean silcgaim_check_silc_dir(GaimConnection *gc)
72 {
73 char filename[256], file_public_key[256], file_private_key[256];
74 char servfilename[256], clientfilename[256], friendsfilename[256];
75 char pkd[256], prd[256];
76 struct stat st;
77 struct passwd *pw;
78 int fd;
79
80 pw = getpwuid(getuid());
81 if (!pw) {
82 gaim_debug_error("silc", "silc: %s\n", strerror(errno));
83 return FALSE;
84 }
85
86 g_snprintf(filename, sizeof(filename) - 1, "%s", silcgaim_silcdir());
87 g_snprintf(servfilename, sizeof(servfilename) - 1, "%s" G_DIR_SEPARATOR_S "serverkeys",
88 silcgaim_silcdir());
89 g_snprintf(clientfilename, sizeof(clientfilename) - 1, "%s" G_DIR_SEPARATOR_S "clientkeys",
90 silcgaim_silcdir());
91 g_snprintf(friendsfilename, sizeof(friendsfilename) - 1, "%s" G_DIR_SEPARATOR_S "friends",
92 silcgaim_silcdir());
93
94 /*
95 * Check ~/.silc directory
96 */
97 if ((g_stat(filename, &st)) == -1) {
98 /* If dir doesn't exist */
99 if (errno == ENOENT) {
100 if (pw->pw_uid == geteuid()) {
101 if ((g_mkdir(filename, 0755)) == -1) {
102 gaim_debug_error("silc", "Couldn't create '%s' directory\n", filename);
103 return FALSE;
104 }
105 } else {
106 gaim_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
107 filename);
108 return FALSE;
109 }
110 } else {
111 gaim_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n", filename, strerror(errno));
112 return FALSE;
113 }
114 } else {
115 #ifndef _WIN32
116 /* Check the owner of the dir */
117 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
118 gaim_debug_error("silc", "You don't seem to own '%s' directory\n",
119 filename);
120 return FALSE;
121 }
122 #endif
123 }
124
125 /*
126 * Check ~./silc/serverkeys directory
127 */
128 if ((g_stat(servfilename, &st)) == -1) {
129 /* If dir doesn't exist */
130 if (errno == ENOENT) {
131 if (pw->pw_uid == geteuid()) {
132 if ((g_mkdir(servfilename, 0755)) == -1) {
133 gaim_debug_error("silc", "Couldn't create '%s' directory\n", servfilename);
134 return FALSE;
135 }
136 } else {
137 gaim_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
138 servfilename);
139 return FALSE;
140 }
141 } else {
142 gaim_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n",
143 servfilename, strerror(errno));
144 return FALSE;
145 }
146 }
147
148 /*
149 * Check ~./silc/clientkeys directory
150 */
151 if ((g_stat(clientfilename, &st)) == -1) {
152 /* If dir doesn't exist */
153 if (errno == ENOENT) {
154 if (pw->pw_uid == geteuid()) {
155 if ((g_mkdir(clientfilename, 0755)) == -1) {
156 gaim_debug_error("silc", "Couldn't create '%s' directory\n", clientfilename);
157 return FALSE;
158 }
159 } else {
160 gaim_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
161 clientfilename);
162 return FALSE;
163 }
164 } else {
165 gaim_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n",
166 clientfilename, strerror(errno));
167 return FALSE;
168 }
169 }
170
171 /*
172 * Check ~./silc/friends directory
173 */
174 if ((g_stat(friendsfilename, &st)) == -1) {
175 /* If dir doesn't exist */
176 if (errno == ENOENT) {
177 if (pw->pw_uid == geteuid()) {
178 if ((g_mkdir(friendsfilename, 0755)) == -1) {
179 gaim_debug_error("silc", "Couldn't create '%s' directory\n", friendsfilename);
180 return FALSE;
181 }
182 } else {
183 gaim_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
184 friendsfilename);
185 return FALSE;
186 }
187 } else {
188 gaim_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n",
189 friendsfilename, strerror(errno));
190 return FALSE;
191 }
192 }
193
194 /*
195 * Check Public and Private keys
196 */
197 g_snprintf(pkd, sizeof(pkd), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcgaim_silcdir());
198 g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcgaim_silcdir());
199 g_snprintf(file_public_key, sizeof(file_public_key) - 1, "%s",
200 gaim_account_get_string(gc->account, "public-key", pkd));
201 g_snprintf(file_private_key, sizeof(file_public_key) - 1, "%s",
202 gaim_account_get_string(gc->account, "private-key", prd));
203
204 if ((g_stat(file_public_key, &st)) == -1) {
205 /* If file doesn't exist */
206 if (errno == ENOENT) {
207 gaim_connection_update_progress(gc, _("Creating SILC key pair..."), 1, 5);
208 if (!silc_create_key_pair(SILCGAIM_DEF_PKCS,
209 SILCGAIM_DEF_PKCS_LEN,
210 file_public_key, file_private_key, NULL,
211 (gc->password == NULL) ? "" : gc->password,
212 NULL, NULL, NULL, FALSE)) {
213 gaim_debug_error("silc", "Couldn't create key pair\n");
214 return FALSE;
215 }
216
217 if ((g_stat(file_public_key, &st)) == -1) {
218 gaim_debug_error("silc", "Couldn't stat '%s' public key, error: %s\n",
219 file_public_key, strerror(errno));
220 return FALSE;
221 }
222 } else {
223 gaim_debug_error("silc", "Couldn't stat '%s' public key, error: %s\n",
224 file_public_key, strerror(errno));
225 return FALSE;
226 }
227 }
228
229 #ifndef _WIN32
230 /* Check the owner of the public key */
231 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
232 gaim_debug_error("silc", "You don't seem to own your public key!?\n");
233 return FALSE;
234 }
235 #endif
236
237 if ((fd = g_open(file_private_key, O_RDONLY, 0)) != -1) {
238 if ((fstat(fd, &st)) == -1) {
239 gaim_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n",
240 file_private_key, strerror(errno));
241 close(fd);
242 return FALSE;
243 }
244 } else if ((g_stat(file_private_key, &st)) == -1) {
245 /* If file doesn't exist */
246 if (errno == ENOENT) {
247 gaim_connection_update_progress(gc, _("Creating SILC key pair..."), 1, 5);
248 if (!silc_create_key_pair(SILCGAIM_DEF_PKCS,
249 SILCGAIM_DEF_PKCS_LEN,
250 file_public_key, file_private_key, NULL,
251 (gc->password == NULL) ? "" : gc->password,
252 NULL, NULL, NULL, FALSE)) {
253 gaim_debug_error("silc", "Couldn't create key pair\n");
254 return FALSE;
255 }
256
257 if ((fd = g_open(file_private_key, O_RDONLY, 0)) != -1) {
258 if ((fstat(fd, &st)) == -1) {
259 gaim_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n",
260 file_private_key, strerror(errno));
261 close(fd);
262 return FALSE;
263 }
264 }
265 /* This shouldn't really happen because silc_create_key_pair()
266 * will set the permissions */
267 else if ((g_stat(file_private_key, &st)) == -1) {
268 gaim_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n",
269 file_private_key, strerror(errno));
270 return FALSE;
271 }
272 } else {
273 gaim_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n",
274 file_private_key, strerror(errno));
275 return FALSE;
276 }
277 }
278
279 #ifndef _WIN32
280 /* Check the owner of the private key */
281 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
282 gaim_debug_error("silc", "You don't seem to own your private key!?\n");
283 if (fd != -1)
284 close(fd);
285 return FALSE;
286 }
287
288 /* Check the permissions for the private key */
289 if ((st.st_mode & 0777) != 0600) {
290 gaim_debug_warning("silc", "Wrong permissions in your private key file `%s'!\n"
291 "Trying to change them ...\n", file_private_key);
292 if ((fd == -1) || (fchmod(fd, S_IRUSR | S_IWUSR)) == -1) {
293 gaim_debug_error("silc",
294 "Failed to change permissions for private key file!\n"
295 "Permissions for your private key file must be 0600.\n");
296 if (fd != -1)
297 close(fd);
298 return FALSE;
299 }
300 gaim_debug_warning("silc", "Done.\n\n");
301 }
302 #endif
303
304 if (fd != -1)
305 close(fd);
306
307 return TRUE;
308 }
309
310 #ifdef _WIN32
311 struct passwd *getpwuid(uid_t uid) {
312 struct passwd *pwd = calloc(1, sizeof(struct passwd));
313 return pwd;
314 }
315
316 uid_t getuid() {
317 return 0;
318 }
319
320 uid_t geteuid() {
321 return 0;
322 }
323 #endif
324
325 void silcgaim_show_public_key(SilcGaim sg,
326 const char *name, SilcPublicKey public_key,
327 GCallback callback, void *context)
328 {
329 SilcPublicKeyIdentifier ident;
330 SilcPKCS pkcs;
331 char *fingerprint, *babbleprint;
332 unsigned char *pk;
333 SilcUInt32 pk_len, key_len = 0;
334 GString *s;
335 char *buf;
336
337 ident = silc_pkcs_decode_identifier(public_key->identifier);
338 if (!ident)
339 return;
340
341 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
342 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
343 babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
344
345 if (silc_pkcs_alloc((unsigned char *)public_key->name, &pkcs)) {
346 key_len = silc_pkcs_public_key_set(pkcs, public_key);
347 silc_pkcs_free(pkcs);
348 }
349
350 s = g_string_new("");
351 if (ident->realname)
352 /* Hint for translators: Please check the tabulator width here and in
353 the next strings (short strings: 2 tabs, longer strings 1 tab,
354 sum: 3 tabs or 24 characters) */
355 g_string_append_printf(s, _("Real Name: \t%s\n"), ident->realname);
356 if (ident->username)
357 g_string_append_printf(s, _("User Name: \t%s\n"), ident->username);
358 if (ident->email)
359 g_string_append_printf(s, _("E-Mail: \t\t%s\n"), ident->email);
360 if (ident->host)
361 g_string_append_printf(s, _("Host Name: \t%s\n"), ident->host);
362 if (ident->org)
363 g_string_append_printf(s, _("Organization: \t%s\n"), ident->org);
364 if (ident->country)
365 g_string_append_printf(s, _("Country: \t%s\n"), ident->country);
366 g_string_append_printf(s, _("Algorithm: \t%s\n"), public_key->name);
367 g_string_append_printf(s, _("Key Length: \t%d bits\n"), (int)key_len);
368 g_string_append_printf(s, "\n");
369 g_string_append_printf(s, _("Public Key Fingerprint:\n%s\n\n"), fingerprint);
370 g_string_append_printf(s, _("Public Key Babbleprint:\n%s"), babbleprint);
371
372 buf = g_string_free(s, FALSE);
373
374 gaim_request_action(sg->gc, _("Public Key Information"),
375 _("Public Key Information"),
376 buf, 0, context, 1,
377 _("Close"), callback);
378
379 g_free(buf);
380 silc_free(fingerprint);
381 silc_free(babbleprint);
382 silc_free(pk);
383 silc_pkcs_free_identifier(ident);
384 }
385
386 SilcAttributePayload
387 silcgaim_get_attr(SilcDList attrs, SilcAttribute attribute)
388 {
389 SilcAttributePayload attr = NULL;
390
391 if (!attrs)
392 return NULL;
393
394 silc_dlist_start(attrs);
395 while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END)
396 if (attribute == silc_attribute_get_attribute(attr))
397 break;
398
399 return attr;
400 }
401
402 void silcgaim_get_umode_string(SilcUInt32 mode, char *buf,
403 SilcUInt32 buf_size)
404 {
405 memset(buf, 0, buf_size);
406 if ((mode & SILC_UMODE_SERVER_OPERATOR) ||
407 (mode & SILC_UMODE_ROUTER_OPERATOR)) {
408 strcat(buf, (mode & SILC_UMODE_SERVER_OPERATOR) ?
409 "[server operator] " :
410 (mode & SILC_UMODE_ROUTER_OPERATOR) ?
411 "[SILC operator] " : "[unknown mode] ");
412 }
413 if (mode & SILC_UMODE_GONE)
414 strcat(buf, "[away] ");
415 if (mode & SILC_UMODE_INDISPOSED)
416 strcat(buf, "[indisposed] ");
417 if (mode & SILC_UMODE_BUSY)
418 strcat(buf, "[busy] ");
419 if (mode & SILC_UMODE_PAGE)
420 strcat(buf, "[wake me up] ");
421 if (mode & SILC_UMODE_HYPER)
422 strcat(buf, "[hyperactive] ");
423 if (mode & SILC_UMODE_ROBOT)
424 strcat(buf, "[robot] ");
425 if (mode & SILC_UMODE_ANONYMOUS)
426 strcat(buf, "[anonymous] ");
427 if (mode & SILC_UMODE_BLOCK_PRIVMSG)
428 strcat(buf, "[blocks private messages] ");
429 if (mode & SILC_UMODE_DETACHED)
430 strcat(buf, "[detached] ");
431 if (mode & SILC_UMODE_REJECT_WATCHING)
432 strcat(buf, "[rejects watching] ");
433 if (mode & SILC_UMODE_BLOCK_INVITE)
434 strcat(buf, "[blocks invites] ");
435 }
436
437 void silcgaim_get_chmode_string(SilcUInt32 mode, char *buf,
438 SilcUInt32 buf_size)
439 {
440 memset(buf, 0, buf_size);
441 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
442 strcat(buf, "[permanent] ");
443 if (mode & SILC_CHANNEL_MODE_PRIVATE)
444 strcat(buf, "[private] ");
445 if (mode & SILC_CHANNEL_MODE_SECRET)
446 strcat(buf, "[secret] ");
447 if (mode & SILC_CHANNEL_MODE_SECRET)
448 strcat(buf, "[secret] ");
449 if (mode & SILC_CHANNEL_MODE_PRIVKEY)
450 strcat(buf, "[private key] ");
451 if (mode & SILC_CHANNEL_MODE_INVITE)
452 strcat(buf, "[invite only] ");
453 if (mode & SILC_CHANNEL_MODE_TOPIC)
454 strcat(buf, "[topic restricted] ");
455 if (mode & SILC_CHANNEL_MODE_ULIMIT)
456 strcat(buf, "[user count limit] ");
457 if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
458 strcat(buf, "[passphrase auth] ");
459 if (mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)
460 strcat(buf, "[public key auth] ");
461 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS)
462 strcat(buf, "[users silenced] ");
463 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS)
464 strcat(buf, "[operators silenced] ");
465 }
466
467 void silcgaim_get_chumode_string(SilcUInt32 mode, char *buf,
468 SilcUInt32 buf_size)
469 {
470 memset(buf, 0, buf_size);
471 if (mode & SILC_CHANNEL_UMODE_CHANFO)
472 strcat(buf, "[founder] ");
473 if (mode & SILC_CHANNEL_UMODE_CHANOP)
474 strcat(buf, "[operator] ");
475 if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)
476 strcat(buf, "[blocks messages] ");
477 if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)
478 strcat(buf, "[blocks user messages] ");
479 if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)
480 strcat(buf, "[blocks robot messages] ");
481 if (mode & SILC_CHANNEL_UMODE_QUIET)
482 strcat(buf, "[quieted] ");
483 }
484
485 void
486 silcgaim_parse_attrs(SilcDList attrs, char **moodstr, char **statusstr,
487 char **contactstr, char **langstr, char **devicestr,
488 char **tzstr, char **geostr)
489 {
490 SilcAttributePayload attr;
491 SilcAttributeMood mood = 0;
492 SilcAttributeContact contact;
493 SilcAttributeObjDevice device;
494 SilcAttributeObjGeo geo;
495
496 char tmp[1024];
497 GString *s;
498
499 *moodstr = NULL;
500 *statusstr = NULL;
501 *contactstr = NULL;
502 *langstr = NULL;
503 *devicestr = NULL;
504 *tzstr = NULL;
505 *geostr = NULL;
506
507 if (!attrs)
508 return;
509
510 s = g_string_new("");
511 attr = silcgaim_get_attr(attrs, SILC_ATTRIBUTE_STATUS_MOOD);
512 if (attr && silc_attribute_get_object(attr, &mood, sizeof(mood))) {
513 if (mood & SILC_ATTRIBUTE_MOOD_HAPPY)
514 g_string_append_printf(s, "[%s] ", _("Happy"));
515 if (mood & SILC_ATTRIBUTE_MOOD_SAD)
516 g_string_append_printf(s, "[%s] ", _("Sad"));
517 if (mood & SILC_ATTRIBUTE_MOOD_ANGRY)
518 g_string_append_printf(s, "[%s] ", _("Angry"));
519 if (mood & SILC_ATTRIBUTE_MOOD_JEALOUS)
520 g_string_append_printf(s, "[%s] ", _("Jealous"));
521 if (mood & SILC_ATTRIBUTE_MOOD_ASHAMED)
522 g_string_append_printf(s, "[%s] ", _("Ashamed"));
523 if (mood & SILC_ATTRIBUTE_MOOD_INVINCIBLE)
524 g_string_append_printf(s, "[%s] ", _("Invincible"));
525 if (mood & SILC_ATTRIBUTE_MOOD_INLOVE)
526 g_string_append_printf(s, "[%s] ", _("In Love"));
527 if (mood & SILC_ATTRIBUTE_MOOD_SLEEPY)
528 g_string_append_printf(s, "[%s] ", _("Sleepy"));
529 if (mood & SILC_ATTRIBUTE_MOOD_BORED)
530 g_string_append_printf(s, "[%s] ", _("Bored"));
531 if (mood & SILC_ATTRIBUTE_MOOD_EXCITED)
532 g_string_append_printf(s, "[%s] ", _("Excited"));
533 if (mood & SILC_ATTRIBUTE_MOOD_ANXIOUS)
534 g_string_append_printf(s, "[%s] ", _("Anxious"));
535 }
536 if (strlen(s->str)) {
537 *moodstr = s->str;
538 g_string_free(s, FALSE);
539 } else
540 g_string_free(s, TRUE);
541
542 attr = silcgaim_get_attr(attrs, SILC_ATTRIBUTE_STATUS_FREETEXT);
543 memset(tmp, 0, sizeof(tmp));
544 if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp)))
545 *statusstr = g_strdup(tmp);
546
547 s = g_string_new("");
548 attr = silcgaim_get_attr(attrs, SILC_ATTRIBUTE_PREFERRED_CONTACT);
549 if (attr && silc_attribute_get_object(attr, &contact, sizeof(contact))) {
550 if (contact & SILC_ATTRIBUTE_CONTACT_CHAT)
551 g_string_append_printf(s, "[%s] ", _("Chat"));
552 if (contact & SILC_ATTRIBUTE_CONTACT_EMAIL)
553 g_string_append_printf(s, "[%s] ", _("E-Mail"));
554 if (contact & SILC_ATTRIBUTE_CONTACT_CALL)
555 g_string_append_printf(s, "[%s] ", _("Phone"));
556 if (contact & SILC_ATTRIBUTE_CONTACT_PAGE)
557 g_string_append_printf(s, "[%s] ", _("Paging"));
558 if (contact & SILC_ATTRIBUTE_CONTACT_SMS)
559 g_string_append_printf(s, "[%s] ", _("SMS"));
560 if (contact & SILC_ATTRIBUTE_CONTACT_MMS)
561 g_string_append_printf(s, "[%s] ", _("MMS"));
562 if (contact & SILC_ATTRIBUTE_CONTACT_VIDEO)
563 g_string_append_printf(s, "[%s] ", _("Video Conferencing"));
564 }
565 if (strlen(s->str)) {
566 *contactstr = s->str;
567 g_string_free(s, FALSE);
568 } else
569 g_string_free(s, TRUE);
570
571 attr = silcgaim_get_attr(attrs, SILC_ATTRIBUTE_PREFERRED_LANGUAGE);
572 memset(tmp, 0, sizeof(tmp));
573 if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp)))
574 *langstr = g_strdup(tmp);
575
576 s = g_string_new("");
577 attr = silcgaim_get_attr(attrs, SILC_ATTRIBUTE_DEVICE_INFO);
578 memset(&device, 0, sizeof(device));
579 if (attr && silc_attribute_get_object(attr, &device, sizeof(device))) {
580 if (device.type == SILC_ATTRIBUTE_DEVICE_COMPUTER)
581 g_string_append_printf(s, "%s: ", _("Computer"));
582 if (device.type == SILC_ATTRIBUTE_DEVICE_MOBILE_PHONE)
583 g_string_append_printf(s, "%s: ", _("Mobile Phone"));
584 if (device.type == SILC_ATTRIBUTE_DEVICE_PDA)
585 g_string_append_printf(s, "%s: ", _("PDA"));
586 if (device.type == SILC_ATTRIBUTE_DEVICE_TERMINAL)
587 g_string_append_printf(s, "%s: ", _("Terminal"));
588 g_string_append_printf(s, "%s %s %s %s",
589 device.manufacturer ? device.manufacturer : "",
590 device.version ? device.version : "",
591 device.model ? device.model : "",
592 device.language ? device.language : "");
593 }
594 if (strlen(s->str)) {
595 *devicestr = s->str;
596 g_string_free(s, FALSE);
597 } else
598 g_string_free(s, TRUE);
599
600 attr = silcgaim_get_attr(attrs, SILC_ATTRIBUTE_TIMEZONE);
601 memset(tmp, 0, sizeof(tmp));
602 if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp)))
603 *tzstr = g_strdup(tmp);
604
605 attr = silcgaim_get_attr(attrs, SILC_ATTRIBUTE_GEOLOCATION);
606 memset(&geo, 0, sizeof(geo));
607 if (attr && silc_attribute_get_object(attr, &geo, sizeof(geo)))
608 *geostr = g_strdup_printf("%s %s %s (%s)",
609 geo.longitude ? geo.longitude : "",
610 geo.latitude ? geo.latitude : "",
611 geo.altitude ? geo.altitude : "",
612 geo.accuracy ? geo.accuracy : "");
613 }
614
615 #ifdef HAVE_SILCMIME_H
616 /* Returns MIME type of filetype */
617
618 char *silcgaim_file2mime(const char *filename)
619 {
620 const char *ct;
621
622 ct = strrchr(filename, '.');
623 if (!ct)
624 return NULL;
625 else if (!strcasecmp(".png", ct))
626 return strdup("image/png");
627 else if (!strcasecmp(".jpg", ct))
628 return strdup("image/jpeg");
629 else if (!strcasecmp(".jpeg", ct))
630 return strdup("image/jpeg");
631 else if (!strcasecmp(".gif", ct))
632 return strdup("image/gif");
633 else if (!strcasecmp(".tiff", ct))
634 return strdup("image/tiff");
635
636 return NULL;
637 }
638
639 /* Checks if message has images, and assembles MIME message if it has.
640 If only one image is present, creates simple MIME image message. If
641 there are multiple images and/or text with images multipart MIME
642 message is created. */
643
644 SilcDList silcgaim_image_message(const char *msg, SilcUInt32 *mflags)
645 {
646 SilcMime mime = NULL, p;
647 SilcDList list, parts = NULL;
648 const char *start, *end, *last;
649 GData *attribs;
650 char *type;
651 gboolean images = FALSE;
652
653 last = msg;
654 while (last && *last && gaim_markup_find_tag("img", last, &start,
655 &end, &attribs)) {
656 GaimStoredImage *image = NULL;
657 const char *id;
658
659 /* Check if there is text before image */
660 if (start - last) {
661 char *text, *tmp;
662 p = silc_mime_alloc();
663
664 /* Add content type */
665 silc_mime_add_field(p, "Content-Type",
666 "text/plain; charset=utf-8");
667
668 tmp = g_strndup(last, start - last);
669 text = gaim_unescape_html(tmp);
670 g_free(tmp);
671 /* Add text */
672 silc_mime_add_data(p, text, strlen(text));
673 g_free(text);
674
675 if (!parts)
676 parts = silc_dlist_init();
677 silc_dlist_add(parts, p);
678 }
679
680 id = g_datalist_get_data(&attribs, "id");
681 if (id && (image = gaim_imgstore_get(atoi(id)))) {
682 unsigned long imglen = gaim_imgstore_get_size(image);
683 gpointer img = gaim_imgstore_get_data(image);
684
685 p = silc_mime_alloc();
686
687 /* Add content type */
688 type = silcgaim_file2mime(gaim_imgstore_get_filename(image));
689 if (!type) {
690 g_datalist_clear(&attribs);
691 last = end + 1;
692 continue;
693 }
694 silc_mime_add_field(p, "Content-Type", type);
695 silc_free(type);
696
697 /* Add content transfer encoding */
698 silc_mime_add_field(p, "Content-Transfer-Encoding", "binary");
699
700 /* Add image data */
701 silc_mime_add_data(p, img, imglen);
702
703 if (!parts)
704 parts = silc_dlist_init();
705 silc_dlist_add(parts, p);
706 images = TRUE;
707 }
708
709 g_datalist_clear(&attribs);
710
711 /* Continue after tag */
712 last = end + 1;
713 }
714
715 /* Check for text after the image(s) */
716 if (images && last && *last) {
717 char *tmp = gaim_unescape_html(last);
718 p = silc_mime_alloc();
719
720 /* Add content type */
721 silc_mime_add_field(p, "Content-Type",
722 "text/plain; charset=utf-8");
723
724 /* Add text */
725 silc_mime_add_data(p, tmp, strlen(tmp));
726 g_free(tmp);
727
728 if (!parts)
729 parts = silc_dlist_init();
730 silc_dlist_add(parts, p);
731 }
732
733 /* If there weren't any images, don't return anything. */
734 if (!images) {
735 if (parts)
736 silc_dlist_uninit(parts);
737 return NULL;
738 }
739
740 if (silc_dlist_count(parts) > 1) {
741 /* Multipart MIME message */
742 char b[32];
743 mime = silc_mime_alloc();
744 silc_mime_add_field(mime, "MIME-Version", "1.0");
745 g_snprintf(b, sizeof(b), "b%4X%4X",
746 (unsigned int)time(NULL),
747 silc_dlist_count(parts));
748 silc_mime_set_multipart(mime, "mixed", b);
749 silc_dlist_start(parts);
750 while ((p = silc_dlist_get(parts)) != SILC_LIST_END)
751 silc_mime_add_multipart(mime, p);
752 } else {
753 /* Simple MIME message */
754 silc_dlist_start(parts);
755 mime = silc_dlist_get(parts);
756 silc_mime_add_field(mime, "MIME-Version", "1.0");
757 }
758
759 *mflags &= ~SILC_MESSAGE_FLAG_UTF8;
760 *mflags |= SILC_MESSAGE_FLAG_DATA;
761
762 /* Encode message. Fragment if it is too large */
763 list = silc_mime_encode_partial(mime, 0xfc00);
764
765 silc_dlist_uninit(parts);
766
767 /* Added multiparts gets freed here */
768 silc_mime_free(mime);
769
770 return list;
771 }
772
773 #endif /* HAVE_SILCMIME_H */