X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Firssi%2Fsrc%2Fsilc%2Fcore%2Fsilc-queries.c;h=18590f767e5d15defcb07a8726b9157fc07e7bf4;hb=be10e71673bc538573b1805ee2115f2a3a7281a2;hp=0d3bbe07fbf5537548414287aaa4b9626b6a31b7;hpb=6bdd7d2dd5279434f63b673e327b43d2513ec3a5;p=silc.git diff --git a/apps/irssi/src/silc/core/silc-queries.c b/apps/irssi/src/silc/core/silc-queries.c index 0d3bbe07..18590f76 100644 --- a/apps/irssi/src/silc/core/silc-queries.c +++ b/apps/irssi/src/silc/core/silc-queries.c @@ -1,43 +1,53 @@ /* - 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 - 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 - 2008 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" -QUERY_REC *silc_query_create(SILC_SERVER_REC *server, - const char *nick, int automatic) +#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" + +static void silc_query_attributes_print_final(bool success, void *context); +static void silc_query_attributes_accept(const char *line, void *context); + +QUERY_REC *silc_query_create(const char *server_tag, + const char *nick, int automatic) { - QUERY_REC *rec; + QUERY_REC *rec; - g_return_val_if_fail(server == NULL || IS_SILC_SERVER(server), NULL); - g_return_val_if_fail(nick != NULL, NULL); + g_return_val_if_fail(nick != NULL, NULL); - rec = g_new0(QUERY_REC, 1); - rec->chat_type = SILC_PROTOCOL; - rec->name = g_strdup(nick); - rec->server = (SERVER_REC *) server; - query_init(rec, automatic); - return rec; + rec = g_new0(QUERY_REC, 1); + rec->chat_type = SILC_PROTOCOL; + rec->name = g_strdup(nick); + rec->server_tag = g_strdup(server_tag); + query_init(rec, automatic); + return rec; } void silc_queries_init(void) @@ -47,3 +57,1029 @@ 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[2], "vcard")) { + silc_client_attribute_del(silc_client, server->conn, + SILC_ATTRIBUTE_USER_INFO, NULL); + settings_set_str("attr_vcard", ""); + } else if (!strcasecmp(argv[2], "services")) { + silc_client_attribute_del(silc_client, server->conn, + SILC_ATTRIBUTE_SERVICE, NULL); + settings_set_str("attr_services", argv[2]); + } else if (!strcasecmp(argv[2], "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[2], "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[2], "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[2], "preferred_language")) { + silc_client_attribute_del(silc_client, server->conn, + SILC_ATTRIBUTE_PREFERRED_LANGUAGE, NULL); + settings_set_str("attr_preferred_language", ""); + } else if (!strcasecmp(argv[2], "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[2], "timezone")) { + return; + } else if (!strcasecmp(argv[2], "geolocation")) { + silc_client_attribute_del(silc_client, server->conn, + SILC_ATTRIBUTE_GEOLOCATION, NULL); + settings_set_str("attr_geolocation", ""); + } else if (!strcasecmp(argv[2], "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[2], "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_language")) { + 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; + SilcMime mime; + SilcAttributeObjGeo geo; + SilcAttributeObjDevice dev; + SilcAttributeObjPk pk; + SilcVCardStruct vcard; + bool allowed; + + memset(&service, 0, sizeof(service)); + memset(&geo, 0, sizeof(geo)); + memset(&dev, 0, sizeof(dev)); + memset(&pk, 0, sizeof(pk)); + memset(&vcard, 0, sizeof(vcard)); + + allowed = settings_get_bool("attr_allow"); + if (!allowed) { + silc_client_attribute_del(silc_client, conn, + SILC_ATTRIBUTE_USER_INFO, NULL); + silc_client_attribute_del(silc_client, conn, + SILC_ATTRIBUTE_SERVICE, NULL); + silc_client_attribute_del(silc_client, conn, + SILC_ATTRIBUTE_STATUS_MOOD, NULL); + silc_client_attribute_del(silc_client, conn, + SILC_ATTRIBUTE_STATUS_FREETEXT, NULL); + silc_client_attribute_del(silc_client, conn, + SILC_ATTRIBUTE_STATUS_MESSAGE, NULL); + silc_client_attribute_del(silc_client, conn, + SILC_ATTRIBUTE_PREFERRED_LANGUAGE, NULL); + silc_client_attribute_del(silc_client, conn, + SILC_ATTRIBUTE_PREFERRED_CONTACT, NULL); + silc_client_attribute_del(silc_client, conn, + SILC_ATTRIBUTE_TIMEZONE, NULL); + silc_client_attribute_del(silc_client, conn, + SILC_ATTRIBUTE_GEOLOCATION, NULL); + silc_client_attribute_del(silc_client, conn, + SILC_ATTRIBUTE_DEVICE_INFO, NULL); + silc_client_attribute_del(silc_client, conn, + SILC_ATTRIBUTE_USER_PUBLIC_KEY, NULL); + return; + } + + 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, NULL); + if (tmp) { + tmp[tmp_len] = 0; + if (silc_vcard_decode(tmp, tmp_len, &vcard)) + silc_client_attribute_add(silc_client, conn, + SILC_ATTRIBUTE_USER_INFO, (void *)&vcard, + sizeof(vcard)); + } + silc_vcard_free(&vcard); + 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; + memset(&service, 0, sizeof(service)); + service.port = atoi(tmp); + *strchr(*entry, ':') = '\0'; + silc_strncat(service.address, sizeof(service.address), *entry, + strlen(*entry)); + service.status = TRUE; + service.idle = 0; + 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, + SILC_32_TO_PTR(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, NULL); + if (tmp) { + mime = silc_mime_decode(NULL, tmp, tmp_len); + if (mime) + 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; + if (!strcasecmp(*entry, "VIDEO")) + mask |= SILC_ATTRIBUTE_CONTACT_VIDEO; + } + silc_client_attribute_add(silc_client, conn, + SILC_ATTRIBUTE_PREFERRED_CONTACT, + SILC_32_TO_PTR(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++) { + if (!strncasecmp(*entry, "silc-rsa:", 8)) { + tmp = silc_file_readfile((*entry) + 8, &tmp_len, NULL); + if (tmp) { + tmp[tmp_len] = 0; + 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); + } else { + silc_say_error("Unsupported public key type '%s'", *entry); + } + } + g_strfreev(list); + } +} + +typedef struct { + SilcClient client; + SILC_SERVER_REC *server; + char *name; + SilcAttributeObjPk userpk; + SilcPublicKey public_key; + SilcVCardStruct vcard; + SilcMime message; + SilcMime extension; + bool nopk; +} *AttrVerify; + +static void silc_query_attributes_verify(SilcBool success, void *context) +{ + *(SilcBool *)context = success; +} + +void silc_query_attributes_print(SILC_SERVER_REC *server, + SilcClient client, + SilcClientConnection conn, + SilcDList attrs, + SilcClientEntry client_entry) +{ + SilcAttributePayload attr; + SilcAttribute attribute; + char tmp[512]; + SilcAttributeObjPk serverpk, usersign, serversign; + AttrVerify verify; + + printformat_module("fe-common/silc", server, NULL, + MSGLEVEL_CRAP, SILCTXT_ATTR_HEADER); + + memset(&serverpk, 0, sizeof(serverpk)); + memset(&usersign, 0, sizeof(usersign)); + memset(&serversign, 0, sizeof(serversign)); + + verify = silc_calloc(1, sizeof(*verify)); + if (!verify) + return; + verify->client = client; + verify->server = server; + verify->name = strdup(client_entry->nickname); + + 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: + { + if (!silc_attribute_get_object(attr, (void *)&verify->vcard, + sizeof(verify->vcard))) + continue; + printformat_module("fe-common/silc", server, NULL, + MSGLEVEL_CRAP, SILCTXT_ATTR_VCARD_FILE, + "present"); + } + break; + + case SILC_ATTRIBUTE_SERVICE: + { + SilcAttributeObjService service; + memset(&service, 0, sizeof(service)); + if (!silc_attribute_get_object(attr, (void *)&service, + sizeof(service))) + continue; + snprintf(tmp, sizeof(tmp) - 1, "%s:%d (logged %s) idle %d seconds", + service.address, (unsigned int)service.port, + service.status ? "in" : "out", + (unsigned int)service.idle); + 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: + { + verify->message = silc_mime_alloc(); + if (!verify->message) + continue; + if (!silc_attribute_get_object(attr, (void *)verify->message, + sizeof(*verify->message))) + continue; + printformat_module("fe-common/silc", server, NULL, + MSGLEVEL_CRAP, SILCTXT_ATTR_STATUS_MESSAGE, + "present"); + } + 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")); + if (mask & SILC_ATTRIBUTE_CONTACT_VIDEO) + silc_strncat(tmp, sizeof(tmp), "VIDEO ", strlen(" VIDEO")); + 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: + { + verify->extension = silc_mime_alloc(); + if (!verify->extension) + continue; + if (!silc_attribute_get_object(attr, (void *)verify->extension, + sizeof(*verify->extension))) + continue; + printformat_module("fe-common/silc", server, NULL, + MSGLEVEL_CRAP, SILCTXT_ATTR_EXTENSION, + "present"); + } + 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 (verify->userpk.type) + continue; + if (!silc_attribute_get_object(attr, (void *)&verify->userpk, + sizeof(verify->userpk))) + continue; + } + break; + + 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; + } + } + + /* Handle the signature verifications and public key verifying here */ + + if (verify->userpk.data) { + SilcPKCSType type = 0; + + if (!strcmp(verify->userpk.type, "silc-rsa")) + type = SILC_PKCS_SILC; + else if (!strcmp(verify->userpk.type, "ssh-rsa")) + type = SILC_PKCS_SSH2; + else if (!strcmp(verify->userpk.type, "x509v3-sign-rsa")) + type = SILC_PKCS_X509V3; + else if (!strcmp(verify->userpk.type, "pgp-sign-rsa")) + type = SILC_PKCS_OPENPGP; + + silc_pkcs_public_key_alloc(type, verify->userpk.data, + verify->userpk.data_len, + &verify->public_key); + } + + if (usersign.data) { + /* Verify the signature now */ + unsigned char *verifyd; + SilcUInt32 verify_len; + SilcBool verified = FALSE; + + if (verify->public_key) { + verifyd = silc_attribute_get_verify_data(attrs, FALSE, &verify_len); + if (verifyd) + silc_pkcs_verify_async(verify->public_key, usersign.data, + usersign.data_len, verifyd, verify_len, + TRUE, sha1hash, + silc_query_attributes_verify, &verified); + + if (verified) { + printformat_module("fe-common/silc", server, NULL, + MSGLEVEL_CRAP, SILCTXT_ATTR_USER_SIGN_VERIFIED); + } else { + printformat_module("fe-common/silc", server, NULL, + MSGLEVEL_CRAP, SILCTXT_ATTR_USER_SIGN_FAILED); + } + + silc_free(verifyd); + } else { + printformat_module("fe-common/silc", server, NULL, + MSGLEVEL_CRAP, SILCTXT_ATTR_USER_SIGN_FAILED); + } + } else { + printformat_module("fe-common/silc", server, NULL, + MSGLEVEL_CRAP, SILCTXT_ATTR_USER_SIGN_NOT_PRESENT); + } + + if (serversign.data) { + /* Verify the signature now */ + SilcPublicKey public_key; + SilcPKCSType type = 0; + unsigned char *verifyd; + SilcUInt32 verify_len; + SilcBool verified = FALSE; + + if (!strcmp(serverpk.type, "silc-rsa")) + type = SILC_PKCS_SILC; + else if (!strcmp(serverpk.type, "ssh-rsa")) + type = SILC_PKCS_SSH2; + else if (!strcmp(serverpk.type, "x509v3-sign-rsa")) + type = SILC_PKCS_X509V3; + else if (!strcmp(serverpk.type, "pgp-sign-rsa")) + type = SILC_PKCS_OPENPGP; + + if (silc_pkcs_public_key_alloc(type, serverpk.data, + serverpk.data_len, + &public_key)) { + verifyd = silc_attribute_get_verify_data(attrs, TRUE, &verify_len); + if (verifyd) + silc_pkcs_verify_async(public_key, serversign.data, + serversign.data_len, verifyd, + verify_len, TRUE, sha1hash, + silc_query_attributes_verify, &verified); + if (verified) { + printformat_module("fe-common/silc", server, NULL, + MSGLEVEL_CRAP, SILCTXT_ATTR_SERVER_SIGN_VERIFIED); + } else { + printformat_module("fe-common/silc", server, NULL, + MSGLEVEL_CRAP, SILCTXT_ATTR_SERVER_SIGN_FAILED); + } + + silc_pkcs_public_key_free(public_key); + silc_free(verifyd); + } else { + printformat_module("fe-common/silc", server, NULL, + MSGLEVEL_CRAP, SILCTXT_ATTR_SERVER_SIGN_FAILED); + } + } + + if (verify->public_key) { + silc_verify_public_key(client, conn, SILC_CONN_CLIENT, + verify->public_key, + silc_query_attributes_print_final, verify); + } else { + verify->nopk = TRUE; + silc_query_attributes_print_final(FALSE, verify); + } +} + +static void silc_query_attributes_print_final(bool success, void *context) +{ + AttrVerify verify = context; + SILC_SERVER_REC *server = verify->server; + char *format = NULL; + unsigned char filename[256], *fingerprint = NULL, *tmp; + struct stat st; + int i; + + if (!verify->nopk) { + if (success) { + printformat_module("fe-common/silc", NULL, NULL, + MSGLEVEL_CRAP, SILCTXT_PUBKEY_VERIFIED, "user", + verify->name); + } else { + printformat_module("fe-common/silc", NULL, NULL, + MSGLEVEL_CRAP, SILCTXT_PUBKEY_NOTVERIFIED, "user", + verify->name); + } + } + + printformat_module("fe-common/silc", server, NULL, + MSGLEVEL_CRAP, SILCTXT_ATTR_FOOTER); + + /* Replace all whitespaces with `_'. */ + fingerprint = silc_hash_fingerprint(sha1hash, + verify->userpk.data, + verify->userpk.data_len); + for (i = 0; i < strlen(fingerprint); i++) + if (fingerprint[i] == ' ') + fingerprint[i] = '_'; + + /* Filename for dir */ + tmp = fingerprint + strlen(fingerprint) - 9; + snprintf(filename, sizeof(filename) - 1, "%s/friends/%s", + get_irssi_dir(), tmp); + silc_free(fingerprint); + + if ((stat(filename, &st)) == -1) { + /* Ask to accept save requested attributes */ + format = format_get_text("fe-common/silc", NULL, NULL, NULL, + SILCTXT_ATTR_SAVE); + keyboard_entry_redirect((SIGNAL_FUNC)silc_query_attributes_accept, + format, 0, verify); + } else { + /* Save new data to existing directory */ + silc_query_attributes_accept("Y", verify); + } + + g_free(format); +} + +static void silc_query_attributes_accept(const char *line, void *context) +{ + AttrVerify verify = context; + SILC_SERVER_REC *server = verify->server; + struct stat st; + struct passwd *pw; + unsigned char filename[256], filename2[256], *fingerprint = NULL, *tmp; + SilcUInt32 len; + int i; + + if (line[0] == 'Y' || line[0] == 'y') { + /* Save the attributes */ + memset(filename, 0, sizeof(filename)); + memset(filename2, 0, sizeof(filename2)); + + pw = getpwuid(getuid()); + if (!pw) + goto out; + + /* Replace all whitespaces with `_'. */ + fingerprint = silc_hash_fingerprint(sha1hash, + verify->userpk.data, + verify->userpk.data_len); + for (i = 0; i < strlen(fingerprint); i++) + if (fingerprint[i] == ' ') + fingerprint[i] = '_'; + + /* Filename for dir */ + tmp = fingerprint + strlen(fingerprint) - 9; + snprintf(filename, sizeof(filename) - 1, "%s/friends/%s", + get_irssi_dir(), tmp); + + /* Create dir if it doesn't exist */ + if ((stat(filename, &st)) == -1) { + /* If dir doesn't exist */ + if (errno == ENOENT) { + if (pw->pw_uid == geteuid()) { + if ((mkdir(filename, 0755)) == -1) { + silc_say_error("Couldn't create `%s' directory", + filename); + goto out; + } + } else { + silc_say_error("Couldn't create `%s' directory due to a " + "wrong uid!", filename); + goto out; + } + } else { + silc_say_error("%s", strerror(errno)); + goto out; + } + } + + /* Save the stuff to the directory */ + + /* Save VCard */ + snprintf(filename2, sizeof(filename2) - 1, "%s/vcard", filename); + if (verify->vcard.full_name) { + tmp = silc_vcard_encode(&verify->vcard, &len); + silc_file_writefile(filename2, tmp, len); + silc_free(tmp); + } + + /* Save public key */ + if (verify->public_key) { + memset(filename2, 0, sizeof(filename2)); + snprintf(filename2, sizeof(filename2) - 1, "%s/clientkey_%s.pub", + filename, fingerprint); + silc_pkcs_save_public_key(filename2, verify->public_key, + SILC_PKCS_FILE_BASE64); + } + + /* Save extension data */ + if (verify->extension) { + memset(filename2, 0, sizeof(filename2)); + snprintf(filename2, sizeof(filename2) - 1, "%s/extension.mime", + filename); + tmp = silc_mime_encode(verify->extension, &len); + if (tmp) + silc_file_writefile(filename2, tmp, len); + } + + /* Save MIME message data */ + if (verify->message) { + memset(filename2, 0, sizeof(filename2)); + snprintf(filename2, sizeof(filename2) - 1, "%s/status_message.mime", + filename); + tmp = silc_mime_encode(verify->message, &len); + if (tmp) + silc_file_writefile(filename2, tmp, len); + } + + printformat_module("fe-common/silc", server, NULL, + MSGLEVEL_CRAP, SILCTXT_ATTR_SAVED, filename); + } + + out: + silc_free(fingerprint); + silc_free(verify->name); + silc_vcard_free(&verify->vcard); + silc_free(verify); +}