Added ATTR command to handle requested attributes for WHOIS.
[silc.git] / apps / irssi / src / silc / core / silc-queries.c
1 /*
2
3   silc-queries.c 
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2002 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 "module.h"
21 #include "signals.h"
22 #include "misc.h"
23 #include "silc-queries.h"
24 #include "settings.h"
25 #include "levels.h"
26 #include "modules.h"
27 #include "commands.h"
28 #include "misc.h"
29
30 #include "fe-common/core/printtext.h"
31 #include "fe-common/core/fe-channels.h"
32 #include "fe-common/core/keyboard.h"
33 #include "fe-common/silc/module-formats.h"
34
35 QUERY_REC *silc_query_create(const char *server_tag,
36                              const char *nick, int automatic)
37 {
38   QUERY_REC *rec;
39
40   g_return_val_if_fail(nick != NULL, NULL);
41
42   rec = g_new0(QUERY_REC, 1);
43   rec->chat_type = SILC_PROTOCOL;
44   rec->name = g_strdup(nick);
45   rec->server_tag = g_strdup(server_tag);
46   query_init(rec, automatic);
47   return rec;
48 }
49
50 void silc_queries_init(void)
51 {
52 }
53
54 void silc_queries_deinit(void)
55 {
56 }
57
58 /* ATTR command */
59
60 void command_attr(const char *data, SILC_SERVER_REC *server,
61                   WI_ITEM_REC *item)
62 {
63   char *tmp;
64   unsigned char **argv;
65   SilcUInt32 argc;
66   SilcUInt32 *argv_lens, *argv_types;
67   const char *sv;
68   bool allowed;
69
70   /* Now parse all arguments */
71   tmp = g_strconcat("ATTR", " ", data, NULL);
72   silc_parse_command_line(tmp, &argv, &argv_lens, &argv_types, &argc, 3);
73   g_free(tmp);
74
75   if (argc == 1) {
76     /* Show all attributes */
77     printformat_module("fe-common/silc", server, NULL,
78                        MSGLEVEL_CRAP, SILCTXT_ATTR_HEADER);
79
80     allowed = settings_get_bool("attr_allow");
81     printformat_module("fe-common/silc", server, NULL,
82                        MSGLEVEL_CRAP, SILCTXT_ATTR_ALLOW,
83                        allowed ? "Yes" : "No");
84
85     sv = settings_get_str("attr_vcard");
86     if (sv && *sv)
87       printformat_module("fe-common/silc", server, NULL,
88                          MSGLEVEL_CRAP, SILCTXT_ATTR_VCARD_FILE, sv);
89
90     sv = settings_get_str("attr_services");
91     if (sv && *sv)
92       printformat_module("fe-common/silc", server, NULL,
93                          MSGLEVEL_CRAP, SILCTXT_ATTR_SERVICES, sv);
94
95     sv = settings_get_str("attr_status_mood");
96     if (sv && *sv)
97       printformat_module("fe-common/silc", server, NULL,
98                          MSGLEVEL_CRAP, SILCTXT_ATTR_STATUS_MOOD, sv);
99
100     sv = settings_get_str("attr_status_text");
101     if (sv && *sv)
102       printformat_module("fe-common/silc", server, NULL,
103                          MSGLEVEL_CRAP, SILCTXT_ATTR_STATUS_TEXT, sv);
104
105     sv = settings_get_str("attr_status_message");
106     if (sv && *sv)
107       printformat_module("fe-common/silc", server, NULL,
108                          MSGLEVEL_CRAP, SILCTXT_ATTR_STATUS_MESSAGE_FILE,
109                          sv);
110
111     sv = settings_get_str("attr_preferred_language");
112     if (sv && *sv)
113       printformat_module("fe-common/silc", server, NULL,
114                          MSGLEVEL_CRAP, SILCTXT_ATTR_PREFERRED_LANGUAGE,
115                          sv);
116
117     sv = settings_get_str("attr_preferred_contact");
118     if (sv && *sv)
119       printformat_module("fe-common/silc", server, NULL,
120                          MSGLEVEL_CRAP, SILCTXT_ATTR_PREFERRED_CONTACT,
121                          sv);
122
123     sv = settings_get_str("attr_geolocation");
124     if (sv && *sv)
125       printformat_module("fe-common/silc", server, NULL,
126                          MSGLEVEL_CRAP, SILCTXT_ATTR_GEOLOCATION,
127                          sv);
128
129     sv = settings_get_str("attr_device_info");
130     if (sv && *sv)
131       printformat_module("fe-common/silc", server, NULL,
132                          MSGLEVEL_CRAP, SILCTXT_ATTR_DEVICE_INFO,
133                          sv);
134
135     sv = settings_get_str("attr_public_keys");
136     if (sv && *sv)
137       printformat_module("fe-common/silc", server, NULL,
138                          MSGLEVEL_CRAP, SILCTXT_ATTR_PUBLIC_KEYS,
139                          sv);
140
141     allowed = settings_get_bool("attr_timezone");
142     printformat_module("fe-common/silc", server, NULL,
143                        MSGLEVEL_CRAP, SILCTXT_ATTR_TIMEZONE_ALLOW,
144                        allowed ? "Yes" : "No");
145
146     printformat_module("fe-common/silc", server, NULL,
147                        MSGLEVEL_CRAP, SILCTXT_ATTR_FOOTER);
148     return;
149   }
150
151   if (argc < 3)
152     cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
153
154   if (!strcasecmp(argv[1], "-del")) {
155     /* Delete attribute */
156     if (!strcasecmp(argv[1], "vcard")) {
157       silc_client_attribute_del(silc_client, server->conn,
158                                 SILC_ATTRIBUTE_USER_INFO, NULL);
159       settings_set_str("attr_vcard", "");
160     } else if (!strcasecmp(argv[1], "services")) {
161       silc_client_attribute_del(silc_client, server->conn,
162                                 SILC_ATTRIBUTE_SERVICE, NULL);
163       settings_set_str("attr_services", argv[2]);
164     } else if (!strcasecmp(argv[1], "status_mood")) {
165       silc_client_attribute_del(silc_client, server->conn,
166                                 SILC_ATTRIBUTE_STATUS_MOOD, NULL);
167       settings_set_str("attr_status_mood", "");
168     } else if (!strcasecmp(argv[1], "status_text")) {
169       silc_client_attribute_del(silc_client, server->conn,
170                                 SILC_ATTRIBUTE_STATUS_FREETEXT, NULL);
171       settings_set_str("attr_status_text", "");
172     } else if (!strcasecmp(argv[1], "status_message")) {
173       silc_client_attribute_del(silc_client, server->conn,
174                                 SILC_ATTRIBUTE_STATUS_MESSAGE, NULL);
175       settings_set_str("attr_status_message", "");
176     } else if (!strcasecmp(argv[1], "preferred_langauge")) {
177       silc_client_attribute_del(silc_client, server->conn,
178                                 SILC_ATTRIBUTE_PREFERRED_LANGUAGE, NULL);
179       settings_set_str("attr_preferred_language", "");
180     } else if (!strcasecmp(argv[1], "preferred_contact")) {
181       silc_client_attribute_del(silc_client, server->conn,
182                                 SILC_ATTRIBUTE_PREFERRED_CONTACT, NULL);
183       settings_set_str("attr_preferred_contact", "");
184     } else if (!strcasecmp(argv[1], "timezone")) {
185       return;
186     } else if (!strcasecmp(argv[1], "geolocation")) {
187       silc_client_attribute_del(silc_client, server->conn,
188                                 SILC_ATTRIBUTE_GEOLOCATION, NULL);
189       settings_set_str("attr_geolocation", "");
190     } else if (!strcasecmp(argv[1], "device_info")) {
191       silc_client_attribute_del(silc_client, server->conn,
192                                 SILC_ATTRIBUTE_DEVICE_INFO, NULL);
193       settings_set_str("attr_device_info", "");
194     } else if (!strcasecmp(argv[1], "public_keys")) {
195       silc_client_attribute_del(silc_client, server->conn,
196                                 SILC_ATTRIBUTE_USER_PUBLIC_KEY, NULL);
197       settings_set_str("attr_public_keys", "");
198     } else {
199       cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
200     }
201     return;
202   }
203
204   /* Add new attribute */
205   if (!strcasecmp(argv[1], "allow")) {
206     allowed = !strcasecmp(argv[2], "ON") || !strcasecmp(argv[2], "YES");
207     settings_set_bool("attr_allow", allowed);
208   } else if (!strcasecmp(argv[1], "vcard")) {
209     settings_set_str("attr_vcard", argv[2]);
210   } else if (!strcasecmp(argv[1], "services")) {
211     settings_set_str("attr_services", argv[2]);
212   } else if (!strcasecmp(argv[1], "status_mood")) {
213     settings_set_str("attr_status_mood", argv[2]);
214   } else if (!strcasecmp(argv[1], "status_text")) {
215     settings_set_str("attr_status_text", argv[2]);
216   } else if (!strcasecmp(argv[1], "status_message")) {
217     settings_set_str("attr_status_message", argv[2]);
218   } else if (!strcasecmp(argv[1], "preferred_langauge")) {
219     settings_set_str("attr_preferred_language", argv[2]);
220   } else if (!strcasecmp(argv[1], "preferred_contact")) {
221     settings_set_str("attr_preferred_contact", argv[2]);
222   } else if (!strcasecmp(argv[1], "timezone")) {
223     allowed = !strcasecmp(argv[2], "ON") || !strcasecmp(argv[2], "YES");
224     settings_set_bool("attr_timezone", allowed);
225   } else if (!strcasecmp(argv[1], "geolocation")) {
226     settings_set_str("attr_geolocation", argv[2]);
227   } else if (!strcasecmp(argv[1], "device_info")) {
228     settings_set_str("attr_device_info", argv[2]);
229   } else if (!strcasecmp(argv[1], "public_keys")) {
230     settings_set_str("attr_public_keys", argv[2]);
231   } else {
232     cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
233   }
234
235   silc_query_attributes_default(silc_client, server->conn);
236 }
237
238 /* Put default attributes to client library */
239
240 void silc_query_attributes_default(SilcClient client,
241                                    SilcClientConnection conn)
242 {
243   char *tmp, **list, **entry;
244   const char *sv;
245   SilcUInt32 tmp_len, mask;
246   SilcAttributeObjService service;
247   SilcAttributeObjMime mime;
248   SilcAttributeObjGeo geo;
249   SilcAttributeObjDevice dev;
250   SilcAttributeObjPk pk;
251   bool allowed;
252
253   memset(&service, 0, sizeof(service));
254   memset(&mime, 0, sizeof(mime));
255   memset(&geo, 0, sizeof(geo));
256   memset(&dev, 0, sizeof(dev));
257   memset(&pk, 0, sizeof(pk));
258
259   sv = settings_get_str("attr_vcard");
260   if (sv && *sv) {
261     /* Put USER_INFO */
262     silc_client_attribute_del(silc_client, conn,
263                               SILC_ATTRIBUTE_USER_INFO, NULL);
264     tmp = silc_file_readfile(sv, &tmp_len);
265     if (tmp)
266       silc_client_attribute_add(silc_client, conn,
267                                 SILC_ATTRIBUTE_USER_INFO, tmp, tmp_len);
268     silc_free(tmp);
269   }
270
271   sv = settings_get_str("attr_services");
272   if (sv && *sv) {
273     /* Put SERVICE */
274     silc_client_attribute_del(silc_client, conn,
275                               SILC_ATTRIBUTE_SERVICE, NULL);
276     list = g_strsplit(sv, " ", -1);
277     for (entry = list; *entry != NULL; entry++) {
278       if (!strchr(*entry, ':'))
279         continue;
280       tmp = strchr(*entry, ':') + 1;
281       if (!tmp || !(*tmp))
282         continue;
283       service.port = atoi(tmp);
284       *strchr(*entry, ':') = '\0';
285       silc_strncat(service.address, sizeof(service.address), *entry,
286                    strlen(*entry));
287       service.status = TRUE;
288       silc_client_attribute_add(silc_client, conn,
289                                 SILC_ATTRIBUTE_SERVICE, &service,
290                                 sizeof(service));
291     }
292     g_strfreev(list);
293   }
294
295   sv = settings_get_str("attr_status_mood");
296   if (sv && *sv) {
297     /* Put STATUS_MOOD */
298     silc_client_attribute_del(silc_client, conn,
299                               SILC_ATTRIBUTE_STATUS_MOOD, NULL);
300     mask = 0;
301     list = g_strsplit(sv, " ", -1);
302     for (entry = list; *entry != NULL; entry++) {
303       if (!strcasecmp(*entry, "NORMAL"))
304         mask |= SILC_ATTRIBUTE_MOOD_NORMAL;
305       if (!strcasecmp(*entry, "HAPPY"))
306         mask |= SILC_ATTRIBUTE_MOOD_HAPPY;
307       if (!strcasecmp(*entry, "SAD"))
308         mask |= SILC_ATTRIBUTE_MOOD_SAD;
309       if (!strcasecmp(*entry, "ANGRY"))
310         mask |= SILC_ATTRIBUTE_MOOD_ANGRY;
311       if (!strcasecmp(*entry, "JEALOUS"))
312         mask |= SILC_ATTRIBUTE_MOOD_JEALOUS;
313       if (!strcasecmp(*entry, "ASHAMED"))
314         mask |= SILC_ATTRIBUTE_MOOD_ASHAMED;
315       if (!strcasecmp(*entry, "INVINCIBLE"))
316         mask |= SILC_ATTRIBUTE_MOOD_INVINCIBLE;
317       if (!strcasecmp(*entry, "INLOVE"))
318         mask |= SILC_ATTRIBUTE_MOOD_INLOVE;
319       if (!strcasecmp(*entry, "SLEEPY"))
320         mask |= SILC_ATTRIBUTE_MOOD_SLEEPY;
321       if (!strcasecmp(*entry, "BORED"))
322         mask |= SILC_ATTRIBUTE_MOOD_BORED;
323       if (!strcasecmp(*entry, "EXCITED"))
324         mask |= SILC_ATTRIBUTE_MOOD_EXCITED;
325       if (!strcasecmp(*entry, "ANXIOUS"))
326         mask |= SILC_ATTRIBUTE_MOOD_ANXIOUS;
327       silc_client_attribute_add(silc_client, conn,
328                                 SILC_ATTRIBUTE_STATUS_MOOD, (void *)mask,
329                                 sizeof(SilcUInt32));
330     }
331     g_strfreev(list);
332   }
333
334   sv = settings_get_str("attr_status_text");
335   if (sv && *sv) {
336     /* Put STATUS_TEXT */
337     silc_client_attribute_del(silc_client, conn,
338                               SILC_ATTRIBUTE_STATUS_FREETEXT, NULL);
339     silc_client_attribute_add(silc_client, conn,
340                               SILC_ATTRIBUTE_STATUS_FREETEXT, (void *)sv,
341                               strlen(sv));
342   }
343
344   sv = settings_get_str("attr_status_message");
345   if (sv && *sv) {
346     /* Put STATUS_MESSAGE */
347     silc_client_attribute_del(silc_client, conn,
348                               SILC_ATTRIBUTE_STATUS_MESSAGE, NULL);
349     tmp = silc_file_readfile(sv, &tmp_len);
350     if (tmp) {
351       mime.mime = (const unsigned char *)tmp;
352       mime.mime_len = tmp_len;
353       silc_client_attribute_add(silc_client, conn,
354                                 SILC_ATTRIBUTE_STATUS_MESSAGE, &mime,
355                                 sizeof(mime));
356     }
357     silc_free(tmp);
358   }
359
360   sv = settings_get_str("attr_preferred_language");
361   if (sv && *sv) {
362     /* Put PREFERRED_LANGUAGE */
363     silc_client_attribute_del(silc_client, conn,
364                               SILC_ATTRIBUTE_PREFERRED_LANGUAGE, NULL);
365     list = g_strsplit(sv, " ", -1);
366     for (entry = list; *entry != NULL; entry++) {
367       silc_client_attribute_add(silc_client, conn,
368                                 SILC_ATTRIBUTE_PREFERRED_LANGUAGE, *entry,
369                                 strlen(*entry));
370     }
371     g_strfreev(list);
372   }
373
374   sv = settings_get_str("attr_preferred_contact");
375   if (sv && *sv) {
376     /* Put PREFERRED_CONTACT */
377     silc_client_attribute_del(silc_client, conn,
378                               SILC_ATTRIBUTE_PREFERRED_CONTACT, NULL);
379     mask = 0;
380     list = g_strsplit(sv, " ", -1);
381     for (entry = list; *entry != NULL; entry++) {
382       if (!strcasecmp(*entry, "NONE"))
383         mask = 0;
384       if (!strcasecmp(*entry, "EMAIL"))
385         mask |= SILC_ATTRIBUTE_CONTACT_EMAIL;
386       if (!strcasecmp(*entry, "CALL"))
387         mask |= SILC_ATTRIBUTE_CONTACT_CALL;
388       if (!strcasecmp(*entry, "PAGE"))
389         mask |= SILC_ATTRIBUTE_CONTACT_PAGE;
390       if (!strcasecmp(*entry, "SMS"))
391         mask |= SILC_ATTRIBUTE_CONTACT_SMS;
392       if (!strcasecmp(*entry, "MMS"))
393         mask |= SILC_ATTRIBUTE_CONTACT_MMS;
394       if (!strcasecmp(*entry, "CHAT"))
395         mask |= SILC_ATTRIBUTE_CONTACT_CHAT;
396       silc_client_attribute_add(silc_client, conn,
397                                 SILC_ATTRIBUTE_PREFERRED_CONTACT, (void *)mask,
398                                 sizeof(SilcUInt32));
399     }
400     g_strfreev(list);
401   }
402
403   /* Put TIMEZONE */
404   allowed = settings_get_bool("attr_timezone");
405   silc_client_attribute_del(silc_client, conn,
406                             SILC_ATTRIBUTE_TIMEZONE, NULL);
407   if (allowed)
408     silc_client_attribute_add(silc_client, conn,
409                               SILC_ATTRIBUTE_TIMEZONE, "foo", 3);
410
411   sv = settings_get_str("attr_geolocation");
412   if (sv && *sv) {
413     /* Put GEOLOCATION */
414     silc_client_attribute_del(silc_client, conn,
415                               SILC_ATTRIBUTE_GEOLOCATION, NULL);
416     list = g_strsplit(sv, ":", -1);
417     for (entry = list; *entry != NULL; entry++) {
418       if (!geo.longitude) {
419         geo.longitude = *entry;
420         continue;
421       }
422       if (!geo.latitude) {
423         geo.latitude = *entry;
424         continue;
425       }
426       if (!geo.altitude) {
427         geo.altitude = *entry;
428         continue;
429       }
430       if (!geo.accuracy) {
431         geo.accuracy = *entry;
432         continue;
433       }
434     }
435     silc_client_attribute_add(silc_client, conn,
436                               SILC_ATTRIBUTE_GEOLOCATION, &geo,
437                               sizeof(geo));
438     g_strfreev(list);
439   }
440
441   sv = settings_get_str("attr_device_info");
442   if (sv && *sv) {
443     /* Put DEVICE_INFO */
444     silc_client_attribute_del(silc_client, conn,
445                               SILC_ATTRIBUTE_DEVICE_INFO, NULL);
446     allowed = FALSE;
447     list = g_strsplit(sv, ":", -1);
448     for (entry = list; *entry != NULL; entry++) {
449       if (!allowed) {
450         allowed = TRUE;
451         if (!strcasecmp(*entry, "COMPUTER"))
452           dev.type = SILC_ATTRIBUTE_DEVICE_COMPUTER;
453         if (!strcasecmp(*entry, "MOBILE_PHONE"))
454           dev.type = SILC_ATTRIBUTE_DEVICE_MOBILE_PHONE;
455         if (!strcasecmp(sv, "PDA"))
456           dev.type = SILC_ATTRIBUTE_DEVICE_PDA;
457         if (!strcasecmp(sv, "TERMINAL"))
458           dev.type = SILC_ATTRIBUTE_DEVICE_TERMINAL;
459         continue;
460       }
461       if (!dev.manufacturer) {
462         dev.manufacturer = *entry;
463         continue;
464       }
465       if (!dev.version) {
466         dev.version = *entry;
467         continue;
468       }
469       if (!dev.model) {
470         dev.model = *entry;
471         continue;
472       }
473       if (!dev.language) {
474         dev.language = *entry;
475         continue;
476       }
477     }
478     silc_client_attribute_add(silc_client, conn,
479                               SILC_ATTRIBUTE_DEVICE_INFO, &dev,
480                               sizeof(dev));
481     g_strfreev(list);
482   }
483
484   sv = settings_get_str("attr_public_keys");
485   if (sv && *sv) {
486     /* Put USER_PUBLIC_KEY */
487     silc_client_attribute_del(silc_client, conn,
488                               SILC_ATTRIBUTE_USER_PUBLIC_KEY, NULL);
489     list = g_strsplit(sv, " ", -1);
490     for (entry = list; *entry != NULL; entry++) {
491       /* XXX we support only SILC keys currently */
492       if (!strncasecmp(*entry, "silc-rsa:", 8)) {
493         tmp = silc_file_readfile((*entry) + 8, &tmp_len);
494         if (tmp) {
495           pk.type = "silc-rsa";
496           pk.data = tmp;
497           pk.data_len = tmp_len;
498           silc_client_attribute_add(silc_client, conn,
499                                     SILC_ATTRIBUTE_USER_PUBLIC_KEY, &pk,
500                                     sizeof(pk));
501         }
502         silc_free(tmp);
503       }
504     }
505     g_strfreev(list);
506   }
507 }
508
509 void silc_query_attributes_print(SILC_SERVER_REC *server,
510                                  SilcClient client,
511                                  SilcClientConnection conn,
512                                  SilcDList attrs)
513 {
514   SilcAttributePayload attr;
515   SilcAttribute attribute;
516   char tmp[512];
517   SilcAttributeObjPk userpk, serverpk, usersign, serversign;
518
519   printformat_module("fe-common/silc", server, NULL,
520                      MSGLEVEL_CRAP, SILCTXT_ATTR_HEADER);
521
522   memset(&userpk, 0, sizeof(userpk));
523   memset(&serverpk, 0, sizeof(serverpk));
524   memset(&usersign, 0, sizeof(usersign));
525   memset(&serversign, 0, sizeof(serversign));
526
527   silc_dlist_start(attrs);
528   while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) {
529     attribute = silc_attribute_get_attribute(attr);
530     memset(tmp, 0, sizeof(tmp));
531
532     switch (attribute) {
533
534     case SILC_ATTRIBUTE_USER_INFO:
535       {
536         SilcVCardStruct vcard;
537         memset(&vcard, 0, sizeof(vcard));
538         if (!silc_attribute_get_object(attr, (void *)&vcard, sizeof(vcard)))
539           continue;
540         /* XXX */
541       }
542       break;
543
544     case SILC_ATTRIBUTE_SERVICE:
545       {
546         SilcAttributeObjService service;
547         if (!silc_attribute_get_object(attr, (void *)&service,
548                                        sizeof(service)))
549           continue;
550         snprintf(tmp, sizeof(tmp) - 1, "%s:%d (logged %s)",
551                  service.address, (unsigned int)service.port,
552                  service.status ? "in" : "out");
553         printformat_module("fe-common/silc", server, NULL,
554                            MSGLEVEL_CRAP, SILCTXT_ATTR_SERVICES, tmp);
555       }
556       break;
557
558     case SILC_ATTRIBUTE_STATUS_MOOD:
559       {
560         SilcUInt32 mask;
561         if (!silc_attribute_get_object(attr, (void *)&mask, sizeof(mask)))
562           continue;
563         if (!mask)
564           silc_strncat(tmp, sizeof(tmp), "NORMAL ", strlen(" NORMAL"));
565         if (mask & SILC_ATTRIBUTE_MOOD_HAPPY)
566           silc_strncat(tmp, sizeof(tmp), "HAPPY ", strlen(" HAPPY"));
567         if (mask & SILC_ATTRIBUTE_MOOD_SAD)
568           silc_strncat(tmp, sizeof(tmp), "SAD ", strlen(" SAD"));
569         if (mask & SILC_ATTRIBUTE_MOOD_ANGRY)
570           silc_strncat(tmp, sizeof(tmp), "ANGRY ", strlen(" ANGRY"));
571         if (mask & SILC_ATTRIBUTE_MOOD_JEALOUS)
572           silc_strncat(tmp, sizeof(tmp), "JEALOUS ", strlen(" JEALOUS"));
573         if (mask & SILC_ATTRIBUTE_MOOD_ASHAMED)
574           silc_strncat(tmp, sizeof(tmp), "ASHAMED ", strlen(" ASHAMED"));
575         if (mask & SILC_ATTRIBUTE_MOOD_INVINCIBLE)
576           silc_strncat(tmp, sizeof(tmp), "INVINCIBLE ", strlen(" INVINCIBLE"));
577         if (mask & SILC_ATTRIBUTE_MOOD_INLOVE)
578           silc_strncat(tmp, sizeof(tmp), "INLOVE ", strlen(" INLOVE"));
579         if (mask & SILC_ATTRIBUTE_MOOD_SLEEPY)
580           silc_strncat(tmp, sizeof(tmp), "SLEEPY ", strlen(" SLEEPY"));
581         if (mask & SILC_ATTRIBUTE_MOOD_BORED)
582           silc_strncat(tmp, sizeof(tmp), "BORED ", strlen(" BORED"));
583         if (mask & SILC_ATTRIBUTE_MOOD_EXCITED)
584           silc_strncat(tmp, sizeof(tmp), "EXCITED ", strlen(" EXCITED"));
585         if (mask & SILC_ATTRIBUTE_MOOD_ANXIOUS)
586           silc_strncat(tmp, sizeof(tmp), "ANXIOUS ", strlen(" ANXIOUS"));
587         printformat_module("fe-common/silc", server, NULL,
588                            MSGLEVEL_CRAP, SILCTXT_ATTR_STATUS_MOOD, tmp);
589       }
590       break;
591
592     case SILC_ATTRIBUTE_STATUS_FREETEXT:
593       {
594         if (!silc_attribute_get_object(attr, (void *)&tmp, sizeof(tmp) - 1))
595           continue;
596         printformat_module("fe-common/silc", server, NULL,
597                            MSGLEVEL_CRAP, SILCTXT_ATTR_STATUS_TEXT, tmp);
598       }
599       break;
600
601     case SILC_ATTRIBUTE_STATUS_MESSAGE:
602       {
603         SilcAttributeObjMime mime;
604         memset(&mime, 0, sizeof(mime));
605         if (!silc_attribute_get_object(attr, (void *)&mime, sizeof(mime)))
606           continue;
607         /* XXX */
608       }
609       break;
610
611     case SILC_ATTRIBUTE_PREFERRED_LANGUAGE:
612       {
613         if (!silc_attribute_get_object(attr, (void *)&tmp, sizeof(tmp) - 1))
614           continue;
615         printformat_module("fe-common/silc", server, NULL,
616                            MSGLEVEL_CRAP, SILCTXT_ATTR_PREFERRED_LANGUAGE,
617                            tmp);
618       }
619       break;
620
621     case SILC_ATTRIBUTE_PREFERRED_CONTACT:
622       {
623         SilcUInt32 mask;
624         if (!silc_attribute_get_object(attr, (void *)&mask, sizeof(mask)))
625           continue;
626         if (!mask)
627           silc_strncat(tmp, sizeof(tmp), "NONE ", strlen(" NONE"));
628         if (mask & SILC_ATTRIBUTE_CONTACT_CHAT)
629           silc_strncat(tmp, sizeof(tmp), "CHAT ", strlen(" CHAT"));
630         if (mask & SILC_ATTRIBUTE_CONTACT_EMAIL)
631           silc_strncat(tmp, sizeof(tmp), "EMAIL ", strlen(" EMAIL"));
632         if (mask & SILC_ATTRIBUTE_CONTACT_CALL)
633           silc_strncat(tmp, sizeof(tmp), "CALL ", strlen(" CALL"));
634         if (mask & SILC_ATTRIBUTE_CONTACT_PAGE)
635           silc_strncat(tmp, sizeof(tmp), "PAGE ", strlen(" PAGE"));
636         if (mask & SILC_ATTRIBUTE_CONTACT_SMS)
637           silc_strncat(tmp, sizeof(tmp), "SMS ", strlen(" SMS"));
638         if (mask & SILC_ATTRIBUTE_CONTACT_MMS)
639           silc_strncat(tmp, sizeof(tmp), "MMS ", strlen(" MMS"));
640         printformat_module("fe-common/silc", server, NULL,
641                            MSGLEVEL_CRAP, SILCTXT_ATTR_PREFERRED_CONTACT, tmp);
642       }
643       break;
644
645     case SILC_ATTRIBUTE_TIMEZONE:
646       {
647         if (!silc_attribute_get_object(attr, (void *)&tmp, sizeof(tmp) - 1))
648           continue;
649         printformat_module("fe-common/silc", server, NULL,
650                            MSGLEVEL_CRAP, SILCTXT_ATTR_TIMEZONE, tmp);
651       }
652       break;
653
654     case SILC_ATTRIBUTE_EXTENSION:
655       break;
656
657     case SILC_ATTRIBUTE_GEOLOCATION:
658       {
659         SilcAttributeObjGeo geo;
660         memset(&geo, 0, sizeof(geo));
661         if (!silc_attribute_get_object(attr, (void *)&geo, sizeof(geo)))
662           continue;
663         snprintf(tmp, sizeof(tmp) - 1, "%s:%s:%s:%s",
664                  geo.longitude ? geo.longitude : "",
665                  geo.latitude ? geo.latitude : "",
666                  geo.altitude ? geo.altitude : "",
667                  geo.accuracy ? geo.accuracy : "");
668         printformat_module("fe-common/silc", server, NULL,
669                            MSGLEVEL_CRAP, SILCTXT_ATTR_GEOLOCATION, tmp);
670       }
671       break;
672
673     case SILC_ATTRIBUTE_DEVICE_INFO:
674       {
675         SilcAttributeObjDevice dev;
676         memset(&dev, 0, sizeof(dev));
677         if (!silc_attribute_get_object(attr, (void *)&dev, sizeof(dev)))
678           continue;
679         snprintf(tmp, sizeof(tmp) - 1, "%s:%s:%s:%s:%s",
680                  (dev.type == SILC_ATTRIBUTE_DEVICE_COMPUTER ? "COMPUTER" :
681                   dev.type == SILC_ATTRIBUTE_DEVICE_PDA ? "PDA" :
682                   dev.type == SILC_ATTRIBUTE_DEVICE_MOBILE_PHONE ?
683                   "MOBILE PHONE" :
684                   dev.type == SILC_ATTRIBUTE_DEVICE_TERMINAL ? "TERMINAL" :
685                   ""),
686                  dev.manufacturer ? dev.manufacturer : "",
687                  dev.version ? dev.version : "",
688                  dev.model ? dev.model: "",
689                  dev.language ? dev.language : "");
690         printformat_module("fe-common/silc", server, NULL,
691                            MSGLEVEL_CRAP, SILCTXT_ATTR_DEVICE_INFO, tmp);
692       }
693       break;
694
695     case SILC_ATTRIBUTE_USER_PUBLIC_KEY:
696       {
697         if (userpk.type)
698           continue;
699         if (!silc_attribute_get_object(attr, (void *)&userpk, sizeof(userpk)))
700           continue;
701       }
702     case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY:
703       {
704         if (serverpk.type)
705           continue;
706         if (!silc_attribute_get_object(attr, (void *)&serverpk,
707                                        sizeof(serverpk)))
708           continue;
709       }
710       break;
711
712     case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE:
713       {
714         if (usersign.data)
715           continue;
716         if (!silc_attribute_get_object(attr, (void *)&usersign,
717                                        sizeof(usersign)))
718           continue;
719       }
720       break;
721
722     case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE:
723       {
724         if (serversign.data)
725           continue;
726         if (!silc_attribute_get_object(attr, (void *)&serversign,
727                                        sizeof(serversign)))
728           continue;
729       }
730       break;
731
732     default:
733       break;
734     }
735   }
736
737   if (!userpk.type)
738     printformat_module("fe-common/silc", server, NULL,
739                        MSGLEVEL_CRAP, SILCTXT_ATTR_FOOTER);
740
741   /* Handle the signature verifications and public key verifying here */
742
743   if (usersign.data && !strcmp(userpk.type, "silc-rsa")) {
744     /* Verify the signature now */
745     /* XXX */
746   }
747
748 }