Added ATTR command to handle requested attributes for WHOIS.
authorPekka Riikonen <priikone@silcnet.org>
Mon, 14 Oct 2002 19:12:49 +0000 (19:12 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Mon, 14 Oct 2002 19:12:49 +0000 (19:12 +0000)
12 files changed:
CHANGES
TODO
apps/irssi/docs/help/in/attr.in [moved from apps/irssi/docs/help/in/my.in with 51% similarity]
apps/irssi/docs/help/in/whois.in
apps/irssi/silc.conf
apps/irssi/src/fe-common/silc/module-formats.c
apps/irssi/src/fe-common/silc/module-formats.h
apps/irssi/src/silc/core/client_ops.c
apps/irssi/src/silc/core/silc-core.c
apps/irssi/src/silc/core/silc-queries.c
apps/irssi/src/silc/core/silc-queries.h
apps/irssi/src/silc/core/silc-servers.c

diff --git a/CHANGES b/CHANGES
index ba624bb6cca99af9a7f4204d80f378b171a756cf..e7f1157e20fa4e87949fe38713b1ae697cc506e8 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,21 @@
+Mon Oct 14 17:55:44 EEST 2002  Pekka Riikonen <priikone@silcnet.org>
+
+       * Periodically remove the NOATTR status from client entry
+         so that the client may take the attributes in use even after
+         server has resolved them unsuccessfully earlier.  Affected
+         file silcd/server_query.c and idlist.h.
+
+       * Moved sha1hash and md5hash from client->internal to
+         SilcClient for application usage.  Affected files are
+         lib/silcclient/client.h and client_internal.h.
+
+       * Fixed attribute encoding and decoding bugs.  Affected
+         files lib/silccore/silcattrs.[ch].
+
+       * Added ATTR command to Irssi SILC Client which is used to      
+         manage user's Requested Attributes sending and values for
+         WHOIS command.  Affected files around Irssi SILC client.
+
 Mon Oct 14 14:33:54 EEST 2002  Pekka Riikonen <priikone@silcnet.org>
 
        * Added silc_buffer_strformat which can be used to format
diff --git a/TODO b/TODO
index 3bf55507473ee768281b0238de56f7d75e9c5317..21087555f4effd90e49c271066d063dfb076b7bd 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,8 +1,7 @@
 TODO/bugs in Irssi SILC client
 ==============================
 
- o Add support for the Requested Attributes in WHOIS (setting information
-   and displaying information).  Do /SET MY_* settings to set them.
+ o Add requested attributes public key/signature verifications.
 
  o Server password is not used at all.  It is not possible to automize
    the password authentication currently.  The silc_get_auth_method
@@ -54,8 +53,6 @@ TODO/bugs In SILC Server
 TODO/bugs In SILC Libraries
 ===========================
 
- o Add support for SILC_ATTRIBUTE_USER_INFo attribute (VCard).
-
  o WIN32 silc_net_create_connection_async does not work the same way
    than on Unix.  Do it with threads on WIN32.  The function works but
    is not actually async currently (Fix this to 0.9.x).
similarity index 51%
rename from apps/irssi/docs/help/in/my.in
rename to apps/irssi/docs/help/in/attr.in
index 0b346b3c51de43a93d3420d933c9648bc11f0e6c..79ee23e032dd2f6f8564fe057396773b0e005794 100644 (file)
 
-My information for WHOIS command
+@SYNTAX:attr@
 
 In SILC it is possible to retrieve detailed information about a user
 with WHOIS command by giving -details option to the WHOIS.  This
 information is retrieved directly from the client, if the client
-supports it.  If client does not support it or do not want to send
+supports it.  This process is called as handling a Requested Attributes 
+in WHOIS.  If client does not support attributes or do not want to send
 anything then server may reply on behalf of the client.
 
 You may set your personal information that others may retrieve using
-WHOIS command.  These information is set with SET command, give command:
+WHOIS command.  These information is set with ATTR command. By default, 
+in SILC Client sending the information is allowed.  If you do not want to 
+allow it give command:
 
-  SET my
-
-to see all possible settings for the information.  By default, in SILC
-Client sending the information is allowed.  If you do not want to allow
-it give command:
-
-   SET my_allow_request OFF
+    ATTR allow OFF
 
 and your client will not reply to the requests.  This usually means that
 server may not send you the request anymore at all, or may do so only
 occasionally.
 
-The following settings are available:
+Adding new information is done with ATTR command as follows:
+
+    ATTR <option> { <value>}
+
+If the <option> already has a value the new value will replace the old
+value.  Deleting all added information for a option is done as follows:
+
+    ATTR -del <option>
 
-  my_vcard
+The following options to ATTR command are available:
+
+  allow
+    - Info:    Allow/Disallow sending of information
+    - Format:  ON/OFF, ON by default
+    - Examples:
+      ATTR allow OFF
+      ATTR allow ON
+
+  vcard
     - Info:    Your personal information (business card)
     - Format:  path to VCard file
     - Examples:
-      SET my_vcard /home/foo/.silc/vcard
+      ATTR vcard /home/foo/.silc/vcard
 
-  my_services
+  services
     - Info:    List of network services you are using
-    - Format:  list of <service>://<address>:<port>
+    - Format:  list of <address>:<port>
     - Examples:
-      SET my_services silc://silcnet.org:706
-      SET my_services silc://silcnet.org:706 irc://irc.org:6667
+      ATTR services silcnet.org:706
+      ATTR services silcnet.org:706 irc.org:6667
 
-  my_status_mood
+  status_mood
     - Info:    Indication of your personal mood at the present time
                By default, setting this is aliased to MOOD command
-    - Format:  list of moods (NORMAL, HAPPY, SAD, ANGRY, JEALOUS,
+    - Format:  list of moods (moods: NORMAL, HAPPY, SAD, ANGRY, JEALOUS,
                                ASHAMED, INVINCIBLE, INLOVE, SLEEPY,
                                BORED, EXCITED, ANXIOUS)
     - Examples:
-      SET my_status_mood HAPPY INLOVE
+      ATTR status_mood HAPPY INLOVE
       MOOD SLEEPY BORED INVINCIBLE
 
-  my_status_text
+  status_text
     - Info:    Text message further describing your current status
     - Format:  text string
     - Examples:
-      SET my_status_text "Not much going on, right now..."
+      ATTR status_text "Not much going on, right now..."
 
-  my_status_message
+  status_message
     - Info:    MIME message further describing your current status
     - Format:  File path to file containing a MIME object
     - Examples:
-      SET my_status_message /home/foo/.silc/message
+      ATTR status_message /home/foo/.silc/message
 
-  my_preferred_language
+  preferred_language
     - Info:    Language you would like to use in SILC
     - Format:  list of three letter language codes (ISO 639-2/T)
                 See http://www.loc.gov/standards/iso639-2/langcodes.html
     - Examples:
-      SET my_preferred_language fin
-      SET my_preferred_language eng fin
+      ATTR preferred_language fin
+      ATTR preferred_language eng fin
 
-  my_preferred_contact
+  preferred_contact
     - Info:    Contact method you prefer
     - Format:  List of preferred contact methods
-               (NONE, EMAIL, CALL, PAGE, SMS, MMS, CHAT)
+               (methods: NONE, EMAIL, CALL, PAGE, SMS, MMS, CHAT)
     - Examples:
-      SET my_preferred_contact NONE
-      SET my_preferred_contact CHAT EMAIL SMS
+      ATTR preferred_contact NONE
+      ATTR preferred_contact CHAT EMAIL SMS
 
-  my_timezone
+  timezone
     - Info:    Send your local time and timezone
     - Format:  ON/OFF, ON by default
     - Examples:
-      SET my_timezone OFF
+      ATTR timezone OFF
 
-  my_geolocation
+  geolocation
     - Info:    Your current measured global location
     - Format:  longitude:latitude:altitude:accuracy in meters
     - Examples:
-      SET my_geolocation "60 10:24 57:251:20"
+      ATTR geolocation "60 10:24 57:251:20"
 
-  my_device_info
+  device_info
     - Info:    Type of your device you are using
-    - Format:  Device type (COMPUTER, MOBILE_PHONE, PDA, TERMINAL)
+    - Format:  Device type:manufacturer:version:model:language
+                (types: COMPUTER, MOBILE_PHONE, PDA, TERMINAL)
     - Examples:
-      SET my_device_info COMPUTER
-      SET my_device_info PDA
+      ATTR device_info COMPUTER:Debian:2.4:Linux:eng
+      ATTR device_info PDA:Palm, Inc.:1.0:Zire,eng
 
-  my_public_keys
+  public_keys
     - Info:    List of your public keys you want to send in the reply,
                 The client automatically sends your SILC public key
     - Format:  List of file paths to public key files with key type
                 (silc-rsa, silc-dss, ssh-rsa, ssh-dss, pgp-sign-rsa,
                 pgp-sign-dss, x509v3-sign-rsa, x509v3-sign-dss)
     - Examples:
-      SET my_public_keys ssh-rsa:/home/priikone/.ssh2/ssh2.pub
-      SET my_public_keys pgp-sign-rsa:/home/priikone/pgp/pgp.asc
-
-See also: WHOIS, SET MY, MOOD
+      ATTR public_keys ssh-rsa:/home/priikone/.ssh2/ssh2.pub
+      ATTR public_keys pgp-sign-rsa:/home/priikone/pgp/pgp.asc
 
+See also: WHOIS, MOOD
index d2a0e2d495d8b6741582da90d7e55371a5a1db8f..1533b0c31805a708981429d0946ffcee7c4d0639 100644 (file)
@@ -24,7 +24,7 @@ some of the information. It also possible that none of these
 informations is received.
 
 If you want to send your information in WHOIS you can set the
-information with SET command. See HELP MY and SET MY.
+information with ATTR command.  See HELP ATTR.
 
-See also: WHOWAS, CHANNEL, SET MY
+See also: WHOWAS, CHANNEL, ATTR
 
index e15b98d84ccdb67249025cf805826c455e53c1bc..aefc8b6a3693a365b1e3fa0121084b6889370250 100644 (file)
@@ -71,7 +71,7 @@ aliases = {
   CALC = "exec - if which bc &>/dev/null\\; then echo '$*' | bc | awk '{print \"$*=\"$$1}'\\; else echo bc was not found\\; fi";
   SBAR = "STATUSBAR";
   Q = "QUERY";
-  MOOD = "SET my_status_mood"
+  MOOD = "ATTR status_mood"
 };
 
 #
index 502a52be629be9065881a33549784d9ed680b8d1..720bd66a8900a444c2adcbeeced96829a8d1188c 100644 (file)
@@ -151,5 +151,31 @@ FORMAT_REC fecommon_silc_formats[] = {
        { "file_error_permission_denied", "Error during file transfer with {nick $0}: Permission denied", 1, { 0 } },
        { "file_close", "File transfer closed with {nick $0} - $1", 2, { 0, 0 } },
 
+       /* Requested Attributes */
+       { NULL, "Requested Attributes", 0 },
+
+       { "attr_header",      "Requested Attributes", 0 },
+       { "attr_footer",      "End of Requested Attributes", 0 },
+       { "attr_allow",       " Sending allowed    : $0", 1, { 0 } },
+       { "attr_vcard_file",  " Business card file : $0", 1, { 0 } },
+       { "attr_services",    " Services used      : $0", 1, { 0 } },
+       { "attr_service",     " Service            : port [$0] address [$1] logged in [$2]", 3, { 0, 0, 0 } },
+       { "attr_status_mood", " User's mood        : $0", 1, { 0 } },
+       { "attr_status_text", " User's message     : $0", 1, { 0 } },
+       { "attr_status_message",      " User's message     : $0", 1, { 0 } },
+       { "attr_status_message_file", " Mmessage file      : $0", 1, { 0 } },
+       { "attr_preferred_language",  " Preferred langauge : $0", 1, { 0 } },
+       { "attr_preferred_contact",   " Preferred contact  : $0", 1, { 0 } },
+       { "attr_geolocation",    " Geolocation        : $0", 1, { 0 } },
+       { "attr_device_info",    " Device Info        : $0", 1, { 0 } },
+       { "attr_public_keys",    " Public keys        : $0", 1, { 0 } },
+       { "attr_timezone",       " Timezone           : $0", 1, { 0 } },
+       { "attr_timezone_allow", " Sending timezone   : $0", 1, { 0 } },
+       { "attr_user_sign_verified",  " User's signature verified successfully", 0 },
+       { "attr_user_sign_failed",    " {hilight User's signature failed}", 0 },
+       { "attr_user_sign_not_present",  " User did not provide digital signature", 0 },
+       { "attr_server_sign_verified",  " Server's signature verified successfully", 0 },
+       { "attr_server_sign_failed",    " {hilight Server's signature failed}", 0 },
+
        { NULL, NULL, 0 }
 };
index e35be86c98774ce22b114655cb8d4f5e9c1e792e..8fdbd386150c2628fe4eb91b6256dcbc01fa9769 100644 (file)
@@ -143,6 +143,31 @@ enum {
   SILCTXT_FILE_ERROR_NO_SUCH_FILE,
   SILCTXT_FILE_ERROR_PERMISSION_DENIED,
   SILCTXT_FILE_CLOSED,
+
+  SILCTXT_FILL_6,
+
+  SILCTXT_ATTR_HEADER,
+  SILCTXT_ATTR_FOOTER,
+  SILCTXT_ATTR_ALLOW,
+  SILCTXT_ATTR_VCARD_FILE,
+  SILCTXT_ATTR_SERVICES,
+  SILCTXT_ATTR_SERVICE,
+  SILCTXT_ATTR_STATUS_MOOD,
+  SILCTXT_ATTR_STATUS_TEXT,
+  SILCTXT_ATTR_STATUS_MESSAGE,
+  SILCTXT_ATTR_STATUS_MESSAGE_FILE,
+  SILCTXT_ATTR_PREFERRED_LANGUAGE,
+  SILCTXT_ATTR_PREFERRED_CONTACT,
+  SILCTXT_ATTR_GEOLOCATION,
+  SILCTXT_ATTR_DEVICE_INFO,
+  SILCTXT_ATTR_PUBLIC_KEYS,
+  SILCTXT_ATTR_TIMEZONE,
+  SILCTXT_ATTR_TIMEZONE_ALLOW,
+  SILCTXT_ATTR_USER_SIGN_VERIFIED,
+  SILCTXT_ATTR_USER_SIGN_FAILED,
+  SILCTXT_ATTR_USER_SIGN_NOT_PRESENT,
+  SILCTXT_ATTR_SERVER_SIGN_VERIFIED,
+  SILCTXT_ATTR_SERVER_SIGN_FAILED,
 };
 
 extern FORMAT_REC fecommon_silc_formats[];
index 407ad720f30fd8a910a0ff2d078459893e513157..732812b889a79648df2bdce38efc324e1e718bf0 100644 (file)
@@ -1092,6 +1092,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
       SilcUInt32 idle, mode;
       SilcBuffer channels, user_modes;
       SilcClientEntry client_entry;
+      SilcDList attrs;
       
       if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
        /* Print the unknown nick for user */
@@ -1136,6 +1137,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
       idle = va_arg(vp, SilcUInt32);
       fingerprint = va_arg(vp, unsigned char *);
       user_modes = va_arg(vp, SilcBuffer);
+      attrs = va_arg(vp, SilcDList);
       
       silc_parse_userfqdn(nickname, &nick, NULL);
       printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
@@ -1199,6 +1201,9 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
                           SILCTXT_WHOIS_FINGERPRINT, fingerprint);
        silc_free(fingerprint);
       }
+
+      if (attrs)
+       silc_query_attributes_print(server, silc_client, conn, attrs);
     }
     break;
     
index f34400e94b7ef76085435de48b2d329aa2135350..9039a5dc5faa6f5b45eb0621c66632cdcf820306 100644 (file)
@@ -40,7 +40,6 @@
 #include "fe-common/silc/module-formats.h"
 
 /* Command line option variables */
-static bool opt_create_keypair = FALSE;
 static char *opt_pkcs = NULL;
 static int opt_bits = 0;
 
@@ -154,9 +153,11 @@ static bool silc_irssi_debug_print(char *file, char *function, int line,
            "DEBUG: %s:%d: %s", function, line, message);
   return TRUE;
 }
+#endif
 
-static void sig_debug_setup_changed(void)
+static void sig_setup_changed(void)
 {
+#ifdef SILC_DEBUG
   bool debug = settings_get_bool("debug");
   if (debug) {
     const char *debug_string = settings_get_str("debug_string");
@@ -168,8 +169,8 @@ static void sig_debug_setup_changed(void)
   }
   if (i_debug)
     silc_debug = FALSE;
-}
 #endif
+}
 
 /* Log callbacks */
 
@@ -362,12 +363,27 @@ void silc_core_init(void)
   settings_add_int("server", "key_exchange_rekey_secs", 3600);
   settings_add_int("server", "connauth_request_secs", 2);
 
+  /* Requested Attributes settings */
+  settings_add_bool("silc", "attr_allow", TRUE);
+  settings_add_str("silc", "attr_vcard", "");
+  settings_add_str("silc", "attr_services", "");
+  settings_add_str("silc", "attr_status_mood", "NORMAL");
+  settings_add_str("silc", "attr_status_text", "");
+  settings_add_str("silc", "attr_status_message", NULL);
+  settings_add_str("silc", "attr_preferred_language", "");
+  settings_add_str("silc", "attr_preferred_contact", "CHAT");
+  settings_add_bool("silc", "attr_timezone", TRUE);
+  settings_add_str("silc", "attr_geolocation", "");
+  settings_add_str("silc", "attr_device_info", NULL);
+  settings_add_str("silc", "attr_public_keys", "");
+
 #ifdef SILC_DEBUG
   settings_add_bool("debug", "debug", FALSE);
   settings_add_str("debug", "debug_string", "");
-  signal_add("setup changed", (SIGNAL_FUNC) sig_debug_setup_changed);
 #endif
 
+  signal_add("setup changed", (SIGNAL_FUNC) sig_setup_changed);
+
   silc_init_userinfo();
 
   /* Initialize client parameters */
@@ -455,10 +471,8 @@ void silc_core_deinit(void)
   if (idletag != -1) {
     signal_emit("chat protocol deinit", 1,
                chat_protocol_find("SILC"));
-#ifdef SILC_DEBUG
-    signal_remove("setup changed", (SIGNAL_FUNC) sig_debug_setup_changed);
-#endif
-    
+    signal_remove("setup changed", (SIGNAL_FUNC) sig_setup_changed);
+
     silc_server_deinit();
     silc_channels_deinit();
     silc_queries_deinit();
index 6717cb3685fa9b1f478c8b57d06a6d8eb1df2e12..a88a9f536d3473af4c11bb82dfed860dc0d4e963 100644 (file)
@@ -1,28 +1,36 @@
 /*
- silc-queries.c : irssi
 
-    Copyright (C) 2000 Timo Sirainen
+  silc-queries.c 
 
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
+  Copyright (C) 2002 Pekka Riikonen
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
 
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
 #include "module.h"
 #include "signals.h"
 #include "misc.h"
-
 #include "silc-queries.h"
+#include "settings.h"
+#include "levels.h"
+#include "modules.h"
+#include "commands.h"
+#include "misc.h"
+
+#include "fe-common/core/printtext.h"
+#include "fe-common/core/fe-channels.h"
+#include "fe-common/core/keyboard.h"
+#include "fe-common/silc/module-formats.h"
 
 QUERY_REC *silc_query_create(const char *server_tag,
                             const char *nick, int automatic)
@@ -46,3 +54,695 @@ void silc_queries_init(void)
 void silc_queries_deinit(void)
 {
 }
+
+/* ATTR command */
+
+void command_attr(const char *data, SILC_SERVER_REC *server,
+                 WI_ITEM_REC *item)
+{
+  char *tmp;
+  unsigned char **argv;
+  SilcUInt32 argc;
+  SilcUInt32 *argv_lens, *argv_types;
+  const char *sv;
+  bool allowed;
+
+  /* Now parse all arguments */
+  tmp = g_strconcat("ATTR", " ", data, NULL);
+  silc_parse_command_line(tmp, &argv, &argv_lens, &argv_types, &argc, 3);
+  g_free(tmp);
+
+  if (argc == 1) {
+    /* Show all attributes */
+    printformat_module("fe-common/silc", server, NULL,
+                      MSGLEVEL_CRAP, SILCTXT_ATTR_HEADER);
+
+    allowed = settings_get_bool("attr_allow");
+    printformat_module("fe-common/silc", server, NULL,
+                      MSGLEVEL_CRAP, SILCTXT_ATTR_ALLOW,
+                      allowed ? "Yes" : "No");
+
+    sv = settings_get_str("attr_vcard");
+    if (sv && *sv)
+      printformat_module("fe-common/silc", server, NULL,
+                        MSGLEVEL_CRAP, SILCTXT_ATTR_VCARD_FILE, sv);
+
+    sv = settings_get_str("attr_services");
+    if (sv && *sv)
+      printformat_module("fe-common/silc", server, NULL,
+                        MSGLEVEL_CRAP, SILCTXT_ATTR_SERVICES, sv);
+
+    sv = settings_get_str("attr_status_mood");
+    if (sv && *sv)
+      printformat_module("fe-common/silc", server, NULL,
+                        MSGLEVEL_CRAP, SILCTXT_ATTR_STATUS_MOOD, sv);
+
+    sv = settings_get_str("attr_status_text");
+    if (sv && *sv)
+      printformat_module("fe-common/silc", server, NULL,
+                        MSGLEVEL_CRAP, SILCTXT_ATTR_STATUS_TEXT, sv);
+
+    sv = settings_get_str("attr_status_message");
+    if (sv && *sv)
+      printformat_module("fe-common/silc", server, NULL,
+                        MSGLEVEL_CRAP, SILCTXT_ATTR_STATUS_MESSAGE_FILE,
+                        sv);
+
+    sv = settings_get_str("attr_preferred_language");
+    if (sv && *sv)
+      printformat_module("fe-common/silc", server, NULL,
+                        MSGLEVEL_CRAP, SILCTXT_ATTR_PREFERRED_LANGUAGE,
+                        sv);
+
+    sv = settings_get_str("attr_preferred_contact");
+    if (sv && *sv)
+      printformat_module("fe-common/silc", server, NULL,
+                        MSGLEVEL_CRAP, SILCTXT_ATTR_PREFERRED_CONTACT,
+                        sv);
+
+    sv = settings_get_str("attr_geolocation");
+    if (sv && *sv)
+      printformat_module("fe-common/silc", server, NULL,
+                        MSGLEVEL_CRAP, SILCTXT_ATTR_GEOLOCATION,
+                        sv);
+
+    sv = settings_get_str("attr_device_info");
+    if (sv && *sv)
+      printformat_module("fe-common/silc", server, NULL,
+                        MSGLEVEL_CRAP, SILCTXT_ATTR_DEVICE_INFO,
+                        sv);
+
+    sv = settings_get_str("attr_public_keys");
+    if (sv && *sv)
+      printformat_module("fe-common/silc", server, NULL,
+                        MSGLEVEL_CRAP, SILCTXT_ATTR_PUBLIC_KEYS,
+                        sv);
+
+    allowed = settings_get_bool("attr_timezone");
+    printformat_module("fe-common/silc", server, NULL,
+                      MSGLEVEL_CRAP, SILCTXT_ATTR_TIMEZONE_ALLOW,
+                      allowed ? "Yes" : "No");
+
+    printformat_module("fe-common/silc", server, NULL,
+                      MSGLEVEL_CRAP, SILCTXT_ATTR_FOOTER);
+    return;
+  }
+
+  if (argc < 3)
+    cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
+
+  if (!strcasecmp(argv[1], "-del")) {
+    /* Delete attribute */
+    if (!strcasecmp(argv[1], "vcard")) {
+      silc_client_attribute_del(silc_client, server->conn,
+                               SILC_ATTRIBUTE_USER_INFO, NULL);
+      settings_set_str("attr_vcard", "");
+    } else if (!strcasecmp(argv[1], "services")) {
+      silc_client_attribute_del(silc_client, server->conn,
+                               SILC_ATTRIBUTE_SERVICE, NULL);
+      settings_set_str("attr_services", argv[2]);
+    } else if (!strcasecmp(argv[1], "status_mood")) {
+      silc_client_attribute_del(silc_client, server->conn,
+                               SILC_ATTRIBUTE_STATUS_MOOD, NULL);
+      settings_set_str("attr_status_mood", "");
+    } else if (!strcasecmp(argv[1], "status_text")) {
+      silc_client_attribute_del(silc_client, server->conn,
+                               SILC_ATTRIBUTE_STATUS_FREETEXT, NULL);
+      settings_set_str("attr_status_text", "");
+    } else if (!strcasecmp(argv[1], "status_message")) {
+      silc_client_attribute_del(silc_client, server->conn,
+                               SILC_ATTRIBUTE_STATUS_MESSAGE, NULL);
+      settings_set_str("attr_status_message", "");
+    } else if (!strcasecmp(argv[1], "preferred_langauge")) {
+      silc_client_attribute_del(silc_client, server->conn,
+                               SILC_ATTRIBUTE_PREFERRED_LANGUAGE, NULL);
+      settings_set_str("attr_preferred_language", "");
+    } else if (!strcasecmp(argv[1], "preferred_contact")) {
+      silc_client_attribute_del(silc_client, server->conn,
+                               SILC_ATTRIBUTE_PREFERRED_CONTACT, NULL);
+      settings_set_str("attr_preferred_contact", "");
+    } else if (!strcasecmp(argv[1], "timezone")) {
+      return;
+    } else if (!strcasecmp(argv[1], "geolocation")) {
+      silc_client_attribute_del(silc_client, server->conn,
+                               SILC_ATTRIBUTE_GEOLOCATION, NULL);
+      settings_set_str("attr_geolocation", "");
+    } else if (!strcasecmp(argv[1], "device_info")) {
+      silc_client_attribute_del(silc_client, server->conn,
+                               SILC_ATTRIBUTE_DEVICE_INFO, NULL);
+      settings_set_str("attr_device_info", "");
+    } else if (!strcasecmp(argv[1], "public_keys")) {
+      silc_client_attribute_del(silc_client, server->conn,
+                               SILC_ATTRIBUTE_USER_PUBLIC_KEY, NULL);
+      settings_set_str("attr_public_keys", "");
+    } else {
+      cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
+    }
+    return;
+  }
+
+  /* Add new attribute */
+  if (!strcasecmp(argv[1], "allow")) {
+    allowed = !strcasecmp(argv[2], "ON") || !strcasecmp(argv[2], "YES");
+    settings_set_bool("attr_allow", allowed);
+  } else if (!strcasecmp(argv[1], "vcard")) {
+    settings_set_str("attr_vcard", argv[2]);
+  } else if (!strcasecmp(argv[1], "services")) {
+    settings_set_str("attr_services", argv[2]);
+  } else if (!strcasecmp(argv[1], "status_mood")) {
+    settings_set_str("attr_status_mood", argv[2]);
+  } else if (!strcasecmp(argv[1], "status_text")) {
+    settings_set_str("attr_status_text", argv[2]);
+  } else if (!strcasecmp(argv[1], "status_message")) {
+    settings_set_str("attr_status_message", argv[2]);
+  } else if (!strcasecmp(argv[1], "preferred_langauge")) {
+    settings_set_str("attr_preferred_language", argv[2]);
+  } else if (!strcasecmp(argv[1], "preferred_contact")) {
+    settings_set_str("attr_preferred_contact", argv[2]);
+  } else if (!strcasecmp(argv[1], "timezone")) {
+    allowed = !strcasecmp(argv[2], "ON") || !strcasecmp(argv[2], "YES");
+    settings_set_bool("attr_timezone", allowed);
+  } else if (!strcasecmp(argv[1], "geolocation")) {
+    settings_set_str("attr_geolocation", argv[2]);
+  } else if (!strcasecmp(argv[1], "device_info")) {
+    settings_set_str("attr_device_info", argv[2]);
+  } else if (!strcasecmp(argv[1], "public_keys")) {
+    settings_set_str("attr_public_keys", argv[2]);
+  } else {
+    cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
+  }
+
+  silc_query_attributes_default(silc_client, server->conn);
+}
+
+/* Put default attributes to client library */
+
+void silc_query_attributes_default(SilcClient client,
+                                  SilcClientConnection conn)
+{
+  char *tmp, **list, **entry;
+  const char *sv;
+  SilcUInt32 tmp_len, mask;
+  SilcAttributeObjService service;
+  SilcAttributeObjMime mime;
+  SilcAttributeObjGeo geo;
+  SilcAttributeObjDevice dev;
+  SilcAttributeObjPk pk;
+  bool allowed;
+
+  memset(&service, 0, sizeof(service));
+  memset(&mime, 0, sizeof(mime));
+  memset(&geo, 0, sizeof(geo));
+  memset(&dev, 0, sizeof(dev));
+  memset(&pk, 0, sizeof(pk));
+
+  sv = settings_get_str("attr_vcard");
+  if (sv && *sv) {
+    /* Put USER_INFO */
+    silc_client_attribute_del(silc_client, conn,
+                             SILC_ATTRIBUTE_USER_INFO, NULL);
+    tmp = silc_file_readfile(sv, &tmp_len);
+    if (tmp)
+      silc_client_attribute_add(silc_client, conn,
+                               SILC_ATTRIBUTE_USER_INFO, tmp, tmp_len);
+    silc_free(tmp);
+  }
+
+  sv = settings_get_str("attr_services");
+  if (sv && *sv) {
+    /* Put SERVICE */
+    silc_client_attribute_del(silc_client, conn,
+                             SILC_ATTRIBUTE_SERVICE, NULL);
+    list = g_strsplit(sv, " ", -1);
+    for (entry = list; *entry != NULL; entry++) {
+      if (!strchr(*entry, ':'))
+       continue;
+      tmp = strchr(*entry, ':') + 1;
+      if (!tmp || !(*tmp))
+       continue;
+      service.port = atoi(tmp);
+      *strchr(*entry, ':') = '\0';
+      silc_strncat(service.address, sizeof(service.address), *entry,
+                  strlen(*entry));
+      service.status = TRUE;
+      silc_client_attribute_add(silc_client, conn,
+                               SILC_ATTRIBUTE_SERVICE, &service,
+                               sizeof(service));
+    }
+    g_strfreev(list);
+  }
+
+  sv = settings_get_str("attr_status_mood");
+  if (sv && *sv) {
+    /* Put STATUS_MOOD */
+    silc_client_attribute_del(silc_client, conn,
+                             SILC_ATTRIBUTE_STATUS_MOOD, NULL);
+    mask = 0;
+    list = g_strsplit(sv, " ", -1);
+    for (entry = list; *entry != NULL; entry++) {
+      if (!strcasecmp(*entry, "NORMAL"))
+       mask |= SILC_ATTRIBUTE_MOOD_NORMAL;
+      if (!strcasecmp(*entry, "HAPPY"))
+       mask |= SILC_ATTRIBUTE_MOOD_HAPPY;
+      if (!strcasecmp(*entry, "SAD"))
+       mask |= SILC_ATTRIBUTE_MOOD_SAD;
+      if (!strcasecmp(*entry, "ANGRY"))
+       mask |= SILC_ATTRIBUTE_MOOD_ANGRY;
+      if (!strcasecmp(*entry, "JEALOUS"))
+       mask |= SILC_ATTRIBUTE_MOOD_JEALOUS;
+      if (!strcasecmp(*entry, "ASHAMED"))
+       mask |= SILC_ATTRIBUTE_MOOD_ASHAMED;
+      if (!strcasecmp(*entry, "INVINCIBLE"))
+       mask |= SILC_ATTRIBUTE_MOOD_INVINCIBLE;
+      if (!strcasecmp(*entry, "INLOVE"))
+       mask |= SILC_ATTRIBUTE_MOOD_INLOVE;
+      if (!strcasecmp(*entry, "SLEEPY"))
+       mask |= SILC_ATTRIBUTE_MOOD_SLEEPY;
+      if (!strcasecmp(*entry, "BORED"))
+       mask |= SILC_ATTRIBUTE_MOOD_BORED;
+      if (!strcasecmp(*entry, "EXCITED"))
+       mask |= SILC_ATTRIBUTE_MOOD_EXCITED;
+      if (!strcasecmp(*entry, "ANXIOUS"))
+       mask |= SILC_ATTRIBUTE_MOOD_ANXIOUS;
+      silc_client_attribute_add(silc_client, conn,
+                               SILC_ATTRIBUTE_STATUS_MOOD, (void *)mask,
+                               sizeof(SilcUInt32));
+    }
+    g_strfreev(list);
+  }
+
+  sv = settings_get_str("attr_status_text");
+  if (sv && *sv) {
+    /* Put STATUS_TEXT */
+    silc_client_attribute_del(silc_client, conn,
+                             SILC_ATTRIBUTE_STATUS_FREETEXT, NULL);
+    silc_client_attribute_add(silc_client, conn,
+                             SILC_ATTRIBUTE_STATUS_FREETEXT, (void *)sv,
+                             strlen(sv));
+  }
+
+  sv = settings_get_str("attr_status_message");
+  if (sv && *sv) {
+    /* Put STATUS_MESSAGE */
+    silc_client_attribute_del(silc_client, conn,
+                             SILC_ATTRIBUTE_STATUS_MESSAGE, NULL);
+    tmp = silc_file_readfile(sv, &tmp_len);
+    if (tmp) {
+      mime.mime = (const unsigned char *)tmp;
+      mime.mime_len = tmp_len;
+      silc_client_attribute_add(silc_client, conn,
+                               SILC_ATTRIBUTE_STATUS_MESSAGE, &mime,
+                               sizeof(mime));
+    }
+    silc_free(tmp);
+  }
+
+  sv = settings_get_str("attr_preferred_language");
+  if (sv && *sv) {
+    /* Put PREFERRED_LANGUAGE */
+    silc_client_attribute_del(silc_client, conn,
+                             SILC_ATTRIBUTE_PREFERRED_LANGUAGE, NULL);
+    list = g_strsplit(sv, " ", -1);
+    for (entry = list; *entry != NULL; entry++) {
+      silc_client_attribute_add(silc_client, conn,
+                               SILC_ATTRIBUTE_PREFERRED_LANGUAGE, *entry,
+                               strlen(*entry));
+    }
+    g_strfreev(list);
+  }
+
+  sv = settings_get_str("attr_preferred_contact");
+  if (sv && *sv) {
+    /* Put PREFERRED_CONTACT */
+    silc_client_attribute_del(silc_client, conn,
+                             SILC_ATTRIBUTE_PREFERRED_CONTACT, NULL);
+    mask = 0;
+    list = g_strsplit(sv, " ", -1);
+    for (entry = list; *entry != NULL; entry++) {
+      if (!strcasecmp(*entry, "NONE"))
+       mask = 0;
+      if (!strcasecmp(*entry, "EMAIL"))
+       mask |= SILC_ATTRIBUTE_CONTACT_EMAIL;
+      if (!strcasecmp(*entry, "CALL"))
+       mask |= SILC_ATTRIBUTE_CONTACT_CALL;
+      if (!strcasecmp(*entry, "PAGE"))
+       mask |= SILC_ATTRIBUTE_CONTACT_PAGE;
+      if (!strcasecmp(*entry, "SMS"))
+       mask |= SILC_ATTRIBUTE_CONTACT_SMS;
+      if (!strcasecmp(*entry, "MMS"))
+       mask |= SILC_ATTRIBUTE_CONTACT_MMS;
+      if (!strcasecmp(*entry, "CHAT"))
+       mask |= SILC_ATTRIBUTE_CONTACT_CHAT;
+      silc_client_attribute_add(silc_client, conn,
+                               SILC_ATTRIBUTE_PREFERRED_CONTACT, (void *)mask,
+                               sizeof(SilcUInt32));
+    }
+    g_strfreev(list);
+  }
+
+  /* Put TIMEZONE */
+  allowed = settings_get_bool("attr_timezone");
+  silc_client_attribute_del(silc_client, conn,
+                           SILC_ATTRIBUTE_TIMEZONE, NULL);
+  if (allowed)
+    silc_client_attribute_add(silc_client, conn,
+                             SILC_ATTRIBUTE_TIMEZONE, "foo", 3);
+
+  sv = settings_get_str("attr_geolocation");
+  if (sv && *sv) {
+    /* Put GEOLOCATION */
+    silc_client_attribute_del(silc_client, conn,
+                             SILC_ATTRIBUTE_GEOLOCATION, NULL);
+    list = g_strsplit(sv, ":", -1);
+    for (entry = list; *entry != NULL; entry++) {
+      if (!geo.longitude) {
+       geo.longitude = *entry;
+       continue;
+      }
+      if (!geo.latitude) {
+       geo.latitude = *entry;
+       continue;
+      }
+      if (!geo.altitude) {
+       geo.altitude = *entry;
+       continue;
+      }
+      if (!geo.accuracy) {
+       geo.accuracy = *entry;
+       continue;
+      }
+    }
+    silc_client_attribute_add(silc_client, conn,
+                             SILC_ATTRIBUTE_GEOLOCATION, &geo,
+                             sizeof(geo));
+    g_strfreev(list);
+  }
+
+  sv = settings_get_str("attr_device_info");
+  if (sv && *sv) {
+    /* Put DEVICE_INFO */
+    silc_client_attribute_del(silc_client, conn,
+                             SILC_ATTRIBUTE_DEVICE_INFO, NULL);
+    allowed = FALSE;
+    list = g_strsplit(sv, ":", -1);
+    for (entry = list; *entry != NULL; entry++) {
+      if (!allowed) {
+       allowed = TRUE;
+       if (!strcasecmp(*entry, "COMPUTER"))
+         dev.type = SILC_ATTRIBUTE_DEVICE_COMPUTER;
+       if (!strcasecmp(*entry, "MOBILE_PHONE"))
+         dev.type = SILC_ATTRIBUTE_DEVICE_MOBILE_PHONE;
+       if (!strcasecmp(sv, "PDA"))
+         dev.type = SILC_ATTRIBUTE_DEVICE_PDA;
+       if (!strcasecmp(sv, "TERMINAL"))
+         dev.type = SILC_ATTRIBUTE_DEVICE_TERMINAL;
+       continue;
+      }
+      if (!dev.manufacturer) {
+       dev.manufacturer = *entry;
+       continue;
+      }
+      if (!dev.version) {
+       dev.version = *entry;
+       continue;
+      }
+      if (!dev.model) {
+       dev.model = *entry;
+       continue;
+      }
+      if (!dev.language) {
+       dev.language = *entry;
+       continue;
+      }
+    }
+    silc_client_attribute_add(silc_client, conn,
+                             SILC_ATTRIBUTE_DEVICE_INFO, &dev,
+                             sizeof(dev));
+    g_strfreev(list);
+  }
+
+  sv = settings_get_str("attr_public_keys");
+  if (sv && *sv) {
+    /* Put USER_PUBLIC_KEY */
+    silc_client_attribute_del(silc_client, conn,
+                             SILC_ATTRIBUTE_USER_PUBLIC_KEY, NULL);
+    list = g_strsplit(sv, " ", -1);
+    for (entry = list; *entry != NULL; entry++) {
+      /* XXX we support only SILC keys currently */
+      if (!strncasecmp(*entry, "silc-rsa:", 8)) {
+       tmp = silc_file_readfile((*entry) + 8, &tmp_len);
+       if (tmp) {
+         pk.type = "silc-rsa";
+         pk.data = tmp;
+         pk.data_len = tmp_len;
+         silc_client_attribute_add(silc_client, conn,
+                                   SILC_ATTRIBUTE_USER_PUBLIC_KEY, &pk,
+                                   sizeof(pk));
+       }
+       silc_free(tmp);
+      }
+    }
+    g_strfreev(list);
+  }
+}
+
+void silc_query_attributes_print(SILC_SERVER_REC *server,
+                                SilcClient client,
+                                SilcClientConnection conn,
+                                SilcDList attrs)
+{
+  SilcAttributePayload attr;
+  SilcAttribute attribute;
+  char tmp[512];
+  SilcAttributeObjPk userpk, serverpk, usersign, serversign;
+
+  printformat_module("fe-common/silc", server, NULL,
+                    MSGLEVEL_CRAP, SILCTXT_ATTR_HEADER);
+
+  memset(&userpk, 0, sizeof(userpk));
+  memset(&serverpk, 0, sizeof(serverpk));
+  memset(&usersign, 0, sizeof(usersign));
+  memset(&serversign, 0, sizeof(serversign));
+
+  silc_dlist_start(attrs);
+  while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) {
+    attribute = silc_attribute_get_attribute(attr);
+    memset(tmp, 0, sizeof(tmp));
+
+    switch (attribute) {
+
+    case SILC_ATTRIBUTE_USER_INFO:
+      {
+       SilcVCardStruct vcard;
+       memset(&vcard, 0, sizeof(vcard));
+       if (!silc_attribute_get_object(attr, (void *)&vcard, sizeof(vcard)))
+         continue;
+       /* XXX */
+      }
+      break;
+
+    case SILC_ATTRIBUTE_SERVICE:
+      {
+       SilcAttributeObjService service;
+       if (!silc_attribute_get_object(attr, (void *)&service,
+                                      sizeof(service)))
+         continue;
+       snprintf(tmp, sizeof(tmp) - 1, "%s:%d (logged %s)",
+                service.address, (unsigned int)service.port,
+                service.status ? "in" : "out");
+       printformat_module("fe-common/silc", server, NULL,
+                          MSGLEVEL_CRAP, SILCTXT_ATTR_SERVICES, tmp);
+      }
+      break;
+
+    case SILC_ATTRIBUTE_STATUS_MOOD:
+      {
+       SilcUInt32 mask;
+       if (!silc_attribute_get_object(attr, (void *)&mask, sizeof(mask)))
+         continue;
+       if (!mask)
+         silc_strncat(tmp, sizeof(tmp), "NORMAL ", strlen(" NORMAL"));
+       if (mask & SILC_ATTRIBUTE_MOOD_HAPPY)
+         silc_strncat(tmp, sizeof(tmp), "HAPPY ", strlen(" HAPPY"));
+       if (mask & SILC_ATTRIBUTE_MOOD_SAD)
+         silc_strncat(tmp, sizeof(tmp), "SAD ", strlen(" SAD"));
+       if (mask & SILC_ATTRIBUTE_MOOD_ANGRY)
+         silc_strncat(tmp, sizeof(tmp), "ANGRY ", strlen(" ANGRY"));
+       if (mask & SILC_ATTRIBUTE_MOOD_JEALOUS)
+         silc_strncat(tmp, sizeof(tmp), "JEALOUS ", strlen(" JEALOUS"));
+       if (mask & SILC_ATTRIBUTE_MOOD_ASHAMED)
+         silc_strncat(tmp, sizeof(tmp), "ASHAMED ", strlen(" ASHAMED"));
+       if (mask & SILC_ATTRIBUTE_MOOD_INVINCIBLE)
+         silc_strncat(tmp, sizeof(tmp), "INVINCIBLE ", strlen(" INVINCIBLE"));
+       if (mask & SILC_ATTRIBUTE_MOOD_INLOVE)
+         silc_strncat(tmp, sizeof(tmp), "INLOVE ", strlen(" INLOVE"));
+       if (mask & SILC_ATTRIBUTE_MOOD_SLEEPY)
+         silc_strncat(tmp, sizeof(tmp), "SLEEPY ", strlen(" SLEEPY"));
+       if (mask & SILC_ATTRIBUTE_MOOD_BORED)
+         silc_strncat(tmp, sizeof(tmp), "BORED ", strlen(" BORED"));
+       if (mask & SILC_ATTRIBUTE_MOOD_EXCITED)
+         silc_strncat(tmp, sizeof(tmp), "EXCITED ", strlen(" EXCITED"));
+       if (mask & SILC_ATTRIBUTE_MOOD_ANXIOUS)
+         silc_strncat(tmp, sizeof(tmp), "ANXIOUS ", strlen(" ANXIOUS"));
+       printformat_module("fe-common/silc", server, NULL,
+                          MSGLEVEL_CRAP, SILCTXT_ATTR_STATUS_MOOD, tmp);
+      }
+      break;
+
+    case SILC_ATTRIBUTE_STATUS_FREETEXT:
+      {
+       if (!silc_attribute_get_object(attr, (void *)&tmp, sizeof(tmp) - 1))
+         continue;
+       printformat_module("fe-common/silc", server, NULL,
+                          MSGLEVEL_CRAP, SILCTXT_ATTR_STATUS_TEXT, tmp);
+      }
+      break;
+
+    case SILC_ATTRIBUTE_STATUS_MESSAGE:
+      {
+       SilcAttributeObjMime mime;
+       memset(&mime, 0, sizeof(mime));
+       if (!silc_attribute_get_object(attr, (void *)&mime, sizeof(mime)))
+         continue;
+       /* XXX */
+      }
+      break;
+
+    case SILC_ATTRIBUTE_PREFERRED_LANGUAGE:
+      {
+       if (!silc_attribute_get_object(attr, (void *)&tmp, sizeof(tmp) - 1))
+         continue;
+       printformat_module("fe-common/silc", server, NULL,
+                          MSGLEVEL_CRAP, SILCTXT_ATTR_PREFERRED_LANGUAGE,
+                          tmp);
+      }
+      break;
+
+    case SILC_ATTRIBUTE_PREFERRED_CONTACT:
+      {
+       SilcUInt32 mask;
+       if (!silc_attribute_get_object(attr, (void *)&mask, sizeof(mask)))
+         continue;
+       if (!mask)
+         silc_strncat(tmp, sizeof(tmp), "NONE ", strlen(" NONE"));
+       if (mask & SILC_ATTRIBUTE_CONTACT_CHAT)
+         silc_strncat(tmp, sizeof(tmp), "CHAT ", strlen(" CHAT"));
+       if (mask & SILC_ATTRIBUTE_CONTACT_EMAIL)
+         silc_strncat(tmp, sizeof(tmp), "EMAIL ", strlen(" EMAIL"));
+       if (mask & SILC_ATTRIBUTE_CONTACT_CALL)
+         silc_strncat(tmp, sizeof(tmp), "CALL ", strlen(" CALL"));
+       if (mask & SILC_ATTRIBUTE_CONTACT_PAGE)
+         silc_strncat(tmp, sizeof(tmp), "PAGE ", strlen(" PAGE"));
+       if (mask & SILC_ATTRIBUTE_CONTACT_SMS)
+         silc_strncat(tmp, sizeof(tmp), "SMS ", strlen(" SMS"));
+       if (mask & SILC_ATTRIBUTE_CONTACT_MMS)
+         silc_strncat(tmp, sizeof(tmp), "MMS ", strlen(" MMS"));
+       printformat_module("fe-common/silc", server, NULL,
+                          MSGLEVEL_CRAP, SILCTXT_ATTR_PREFERRED_CONTACT, tmp);
+      }
+      break;
+
+    case SILC_ATTRIBUTE_TIMEZONE:
+      {
+       if (!silc_attribute_get_object(attr, (void *)&tmp, sizeof(tmp) - 1))
+         continue;
+       printformat_module("fe-common/silc", server, NULL,
+                          MSGLEVEL_CRAP, SILCTXT_ATTR_TIMEZONE, tmp);
+      }
+      break;
+
+    case SILC_ATTRIBUTE_EXTENSION:
+      break;
+
+    case SILC_ATTRIBUTE_GEOLOCATION:
+      {
+       SilcAttributeObjGeo geo;
+       memset(&geo, 0, sizeof(geo));
+       if (!silc_attribute_get_object(attr, (void *)&geo, sizeof(geo)))
+         continue;
+       snprintf(tmp, sizeof(tmp) - 1, "%s:%s:%s:%s",
+                geo.longitude ? geo.longitude : "",
+                geo.latitude ? geo.latitude : "",
+                geo.altitude ? geo.altitude : "",
+                geo.accuracy ? geo.accuracy : "");
+       printformat_module("fe-common/silc", server, NULL,
+                          MSGLEVEL_CRAP, SILCTXT_ATTR_GEOLOCATION, tmp);
+      }
+      break;
+
+    case SILC_ATTRIBUTE_DEVICE_INFO:
+      {
+       SilcAttributeObjDevice dev;
+       memset(&dev, 0, sizeof(dev));
+       if (!silc_attribute_get_object(attr, (void *)&dev, sizeof(dev)))
+         continue;
+       snprintf(tmp, sizeof(tmp) - 1, "%s:%s:%s:%s:%s",
+                (dev.type == SILC_ATTRIBUTE_DEVICE_COMPUTER ? "COMPUTER" :
+                 dev.type == SILC_ATTRIBUTE_DEVICE_PDA ? "PDA" :
+                 dev.type == SILC_ATTRIBUTE_DEVICE_MOBILE_PHONE ?
+                 "MOBILE PHONE" :
+                 dev.type == SILC_ATTRIBUTE_DEVICE_TERMINAL ? "TERMINAL" :
+                 ""),
+                dev.manufacturer ? dev.manufacturer : "",
+                dev.version ? dev.version : "",
+                dev.model ? dev.model: "",
+                dev.language ? dev.language : "");
+       printformat_module("fe-common/silc", server, NULL,
+                          MSGLEVEL_CRAP, SILCTXT_ATTR_DEVICE_INFO, tmp);
+      }
+      break;
+
+    case SILC_ATTRIBUTE_USER_PUBLIC_KEY:
+      {
+       if (userpk.type)
+         continue;
+       if (!silc_attribute_get_object(attr, (void *)&userpk, sizeof(userpk)))
+         continue;
+      }
+    case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY:
+      {
+       if (serverpk.type)
+         continue;
+       if (!silc_attribute_get_object(attr, (void *)&serverpk,
+                                      sizeof(serverpk)))
+         continue;
+      }
+      break;
+
+    case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE:
+      {
+       if (usersign.data)
+         continue;
+       if (!silc_attribute_get_object(attr, (void *)&usersign,
+                                      sizeof(usersign)))
+         continue;
+      }
+      break;
+
+    case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE:
+      {
+       if (serversign.data)
+         continue;
+       if (!silc_attribute_get_object(attr, (void *)&serversign,
+                                      sizeof(serversign)))
+         continue;
+      }
+      break;
+
+    default:
+      break;
+    }
+  }
+
+  if (!userpk.type)
+    printformat_module("fe-common/silc", server, NULL,
+                      MSGLEVEL_CRAP, SILCTXT_ATTR_FOOTER);
+
+  /* Handle the signature verifications and public key verifying here */
+
+  if (usersign.data && !strcmp(userpk.type, "silc-rsa")) {
+    /* Verify the signature now */
+    /* XXX */
+  }
+
+}
index 9443b59cc7e22b379111241afb0f1359c341b156..e5ea6c29deba0b91eed9196ca48c95d7c71aacda 100644 (file)
@@ -1,5 +1,24 @@
-#ifndef __SILC_QUERIES_H
-#define __SILC_QUERIES_H
+/*
+
+  silc-queries.h 
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2002 Pekka Riikonen
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+*/
+
+#ifndef SILC_QUERIES_H
+#define SILC_QUERIES_H
 
 #include "chat-protocols.h"
 #include "queries.h"
@@ -17,5 +36,13 @@ QUERY_REC *silc_query_create(const char *server_tag,
                             const char *nick, int automatic);
 void silc_queries_init(void);
 void silc_queries_deinit(void);
+void command_attr(const char *data, SILC_SERVER_REC *server,
+                 WI_ITEM_REC *item);
+void silc_query_attributes_default(SilcClient client,
+                                  SilcClientConnection conn);
+void silc_query_attributes_print(SILC_SERVER_REC *server,
+                                SilcClient client,
+                                SilcClientConnection conn,
+                                SilcDList attrs);
 
-#endif
+#endif /* SILC_QUERIES_H */
index 731298dda13ce798865e1b5f7102466184df1f0b..301ce99751aa2b93b26e48fefb7def325b8fe6c2 100644 (file)
@@ -294,6 +294,9 @@ static void sig_connected(SILC_SERVER_REC *server)
   /* Start key exchange with the server */
   silc_client_start_key_exchange(silc_client, conn, fd);
 
+  /* Put default attributes */
+  silc_query_attributes_default(silc_client, conn);
+
   server->ftp_sessions = silc_dlist_init();
   server->isnickflag = isnickflag_func;
   server->ischannel = ischannel_func;
@@ -415,6 +418,7 @@ char *silc_server_get_channels(SILC_SERVER_REC *server)
 /* SYNTAX: DETACH */
 /* SYNTAX: WATCH [<-add | -del> <nickname>] */
 /* SYNTAX: STATS */
+/* SYNTAX: ATTR [<-del> <option> [{ <value>}]] */
 
 void silc_command_exec(SILC_SERVER_REC *server,
                       const char *command, const char *args)
@@ -968,6 +972,7 @@ void silc_server_init(void)
   command_bind_silc("detach", MODULE_NAME, (SIGNAL_FUNC) command_self);
   command_bind_silc("watch", MODULE_NAME, (SIGNAL_FUNC) command_self);
   command_bind_silc("stats", MODULE_NAME, (SIGNAL_FUNC) command_self);
+  command_bind_silc("attr", MODULE_NAME, (SIGNAL_FUNC) command_attr);
 
   command_set_options("connect", "+silcnet");
 }
@@ -1005,6 +1010,7 @@ void silc_server_deinit(void)
   command_unbind("detach", (SIGNAL_FUNC) command_self);
   command_unbind("watch", (SIGNAL_FUNC) command_self);
   command_unbind("stats", (SIGNAL_FUNC) command_self);
+  command_unbind("attr", (SIGNAL_FUNC) command_attr);
 }
 
 void silc_server_free_ftp(SILC_SERVER_REC *server,