diff options
26 files changed, 2 insertions, 10453 deletions
diff --git a/libpurple/protocols/meson.build b/libpurple/protocols/meson.build index bf769d8408..412ddc0f7b 100644 --- a/libpurple/protocols/meson.build +++ b/libpurple/protocols/meson.build @@ -7,5 +7,4 @@ subdir('ircv3') subdir('jabber') subdir('novell') subdir('sametime') -subdir('silc') subdir('zephyr') diff --git a/libpurple/protocols/silc/README b/libpurple/protocols/silc/README deleted file mode 100644 index c8c5ab532f..0000000000 --- a/libpurple/protocols/silc/README +++ /dev/null @@ -1,31 +0,0 @@ -SILC Purple Plugin -================== - -This is the Purple protocol plugin of the protocol called Secure Internet -Live Conferencing (SILC). The implementation will use the SILC Toolkit, -freely available from the http://silcnet.org/ site, for the actual SILC -protocol implementation. - -To include SILC into Purple, one needs to first compile and install -the SILC Toolkit. It is done as follows: - - ./configure - make - make install - -This will compile shared libraries of the SILC Toolkit. If the --prefix -is not given to ./configure, the binaries are installed into the -/usr/local/silc directory. - -Once the Toolkit is installed one needs to tell Purple's ./configure -script where the SILC Toolkit is located. It is done as simply as: - - ./configure - -if pkg-config is installed in your system. If it is isn't it's done as: - - ./configure --with-silc-libs=/path/to/silc/lib - --with-silc-includes=/path/to/silc/include - -If the SILC Toolkit cannot be found then the SILC protocol plugin will -not be compiled. diff --git a/libpurple/protocols/silc/TODO b/libpurple/protocols/silc/TODO deleted file mode 100644 index 81fae64390..0000000000 --- a/libpurple/protocols/silc/TODO +++ /dev/null @@ -1,6 +0,0 @@ -Features TODO (maybe) -===================== - -Preferences - - Add joined channels to buddy list automatically (during - session) diff --git a/libpurple/protocols/silc/buddy.c b/libpurple/protocols/silc/buddy.c deleted file mode 100644 index 5e1743fff8..0000000000 --- a/libpurple/protocols/silc/buddy.c +++ /dev/null @@ -1,1749 +0,0 @@ -/* - - silcpurple_buddy.c - - Author: Pekka Riikonen <priikone@silcnet.org> - - Copyright (C) 2004 - 2007 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. - -*/ - -#include <glib/gi18n-lib.h> -#include <glib/gstdio.h> - -#include "libpurple/glibcompat.h" - -#include "silcpurple.h" -#include "wb.h" - -/***************************** Key Agreement *********************************/ - -static void -silcpurple_buddy_keyagr(PurpleBlistNode *node, gpointer data); - -static void -silcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name, - gboolean force_local); - -static void -silcpurple_buddy_keyagr_resolved(SilcClient client, - SilcClientConnection conn, - SilcStatus status, - SilcDList clients, - void *context) -{ - PurpleConnection *gc = client->application; - char *nick = context; - - if (!clients) { - char tmp[256]; - - g_snprintf(tmp, sizeof(tmp), - _("User %s is not present in the network"), nick); - purple_notify_error(gc, _("Key Agreement"), - _("Cannot perform the key agreement"), tmp, - purple_request_cpar_from_connection(gc)); - } else { - silcpurple_buddy_keyagr_do(gc, nick, FALSE); - } - - g_free(nick); -} - -static void -silcpurple_buddy_keyagr_cb(SilcClient client, - SilcClientConnection conn, - SilcClientEntry client_entry, - SilcKeyAgreementStatus status, - SilcSKEKeyMaterial key, - void *context) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = purple_connection_get_protocol_data(gc); - - if (!sg->conn) - return; - - switch (status) { - case SILC_KEY_AGREEMENT_OK: - { - PurpleConversation *im; - PurpleConversationManager *manager; - char tmp[128]; - - /* Set the private key for this client */ - silc_client_del_private_message_key(client, conn, client_entry); - silc_client_add_private_message_key_ske(client, conn, client_entry, - NULL, NULL, key); - silc_ske_free_key_material(key); - - manager = purple_conversation_manager_get_default(); - - /* Open IM window */ - im = purple_conversation_manager_find_im(manager, sg->account, - client_entry->nickname); - if (im) { - /* we don't have windows in the core anymore...but we may want to - * provide some method for asking the UI to show the window - purple_conversation_window_show(purple_conversation_get_window(im)); - */ - } else { - im = purple_im_conversation_new(sg->account, - client_entry->nickname); - } - g_snprintf(tmp, sizeof(tmp), "%s [private key]", client_entry->nickname); - purple_conversation_set_title(im, tmp); - } - break; - - case SILC_KEY_AGREEMENT_ERROR: - purple_notify_error(gc, _("Key Agreement"), - _("Error occurred during key agreement"), NULL, - purple_request_cpar_from_connection(gc)); - break; - - case SILC_KEY_AGREEMENT_FAILURE: - purple_notify_error(gc, _("Key Agreement"), - _("Key Agreement failed"), NULL, - purple_request_cpar_from_connection(gc)); - break; - - case SILC_KEY_AGREEMENT_TIMEOUT: - purple_notify_error(gc, _("Key Agreement"), - _("Timeout during key agreement"), NULL, - purple_request_cpar_from_connection(gc)); - break; - - case SILC_KEY_AGREEMENT_ABORTED: - purple_notify_error(gc, _("Key Agreement"), - _("Key agreement was aborted"), NULL, - purple_request_cpar_from_connection(gc)); - break; - - case SILC_KEY_AGREEMENT_ALREADY_STARTED: - purple_notify_error(gc, _("Key Agreement"), _("Key agreement is" - " already started"), NULL, - purple_request_cpar_from_connection(gc)); - break; - - case SILC_KEY_AGREEMENT_SELF_DENIED: - purple_notify_error(gc, _("Key Agreement"), _("Key agreement " - "cannot be started with yourself"), NULL, - purple_request_cpar_from_connection(gc)); - break; - - default: - break; - } -} - -static void -silcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name, - gboolean force_local) -{ - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcDList clients; - SilcClientEntry client_entry; - SilcClientConnectionParams params; - char *local_ip = NULL, *remote_ip = NULL; - gboolean local = TRUE; - SilcSocket sock; - - if (!sg->conn || !name) - return; - - /* Find client entry */ - clients = silc_client_get_clients_local(sg->client, sg->conn, name, - FALSE); - if (!clients) { - /* Resolve unknown user */ - silc_client_get_clients(sg->client, sg->conn, name, NULL, - silcpurple_buddy_keyagr_resolved, g_strdup(name)); - return; - } - - silc_socket_stream_get_info(silc_packet_stream_get_stream(sg->conn->stream), - &sock, NULL, NULL, NULL); - - /* Resolve the local IP from the outgoing socket connection. We resolve - it to check whether we have a private range IP address or public IP - address. If we have public then we will assume that we are not behind - NAT and will provide automatically the point of connection to the - agreement. If we have private range address we assume that we are - behind NAT and we let the responder provide the point of connection. - - The algorithm also checks the remote IP address of server connection. - If it is private range address and we have private range address we - assume that we are chatting in LAN and will provide the point of - connection. - - Naturally this algorithm does not always get things right. */ - - if (silc_net_check_local_by_sock(sock, NULL, &local_ip)) { - /* Check if the IP is private */ - if (!force_local && silcpurple_ip_is_private(local_ip)) { - local = FALSE; - - /* Local IP is private, resolve the remote server IP to see whether - we are talking to Internet or just on LAN. */ - if (silc_net_check_host_by_sock(sock, NULL, - &remote_ip)) - if (silcpurple_ip_is_private(remote_ip)) - /* We assume we are in LAN. Let's provide - the connection point. */ - local = TRUE; - } - } - - if (force_local) - local = TRUE; - - if (local && !local_ip) - local_ip = silc_net_localip(); - - silc_dlist_start(clients); - client_entry = silc_dlist_get(clients); - - memset(¶ms, 0, sizeof(params)); - params.timeout_secs = 60; - if (local) - /* Provide connection point */ - params.local_ip = local_ip; - - /* Send the key agreement request */ - silc_client_send_key_agreement(sg->client, sg->conn, client_entry, - ¶ms, sg->public_key, - sg->private_key, - silcpurple_buddy_keyagr_cb, NULL); - - silc_free(local_ip); - silc_free(remote_ip); - silc_client_list_free(sg->client, sg->conn, clients); -} - -typedef struct { - SilcClient client; - SilcClientConnection conn; - SilcClientID client_id; - char *hostname; - SilcUInt16 port; -} *SilcPurpleKeyAgrAsk; - -static void -silcpurple_buddy_keyagr_request_cb(SilcPurpleKeyAgrAsk a, gint id) -{ - SilcClientEntry client_entry; - SilcClientConnectionParams params; - - if (id != 1) - goto out; - - /* Get the client entry. */ - client_entry = silc_client_get_client_by_id(a->client, a->conn, - &a->client_id); - if (!client_entry) { - purple_notify_error(a->client->application, _("Key Agreement"), - _("The remote user is not present in the network any more"), - NULL, NULL); - goto out; - } - - /* If the hostname was provided by the requestor perform the key agreement - now. Otherwise, we will send him a request to connect to us. */ - if (a->hostname) { - memset(¶ms, 0, sizeof(params)); - params.timeout_secs = 60; - silc_client_perform_key_agreement(a->client, a->conn, - client_entry, ¶ms, - a->conn->public_key, - a->conn->private_key, - a->hostname, a->port, - silcpurple_buddy_keyagr_cb, NULL); - } else { - /* Send request. Force us as the point of connection since requestor - did not provide the point of connection. */ - silcpurple_buddy_keyagr_do(a->client->application, - client_entry->nickname, TRUE); - } - - out: - g_free(a->hostname); - silc_free(a); -} - -void silcpurple_buddy_keyagr_request(SilcClient client, - SilcClientConnection conn, - SilcClientEntry client_entry, - const char *hostname, SilcUInt16 port, - SilcUInt16 protocol) -{ - char tmp[128], tmp2[128]; - SilcPurpleKeyAgrAsk a; - PurpleConnection *gc = client->application; - - /* For now Pidgin don't support UDP key agreement */ - if (protocol == 1) - return; - - g_snprintf(tmp, sizeof(tmp), - _("Key agreement request received from %s. Would you like to " - "perform the key agreement?"), client_entry->nickname); - if (hostname) - g_snprintf(tmp2, sizeof(tmp2), - _("The remote user is waiting key agreement on:\n" - "Remote host: %s\nRemote port: %d"), hostname, port); - - a = silc_calloc(1, sizeof(*a)); - if (!a) - return; - a->client = client; - a->conn = conn; - a->client_id = client_entry->id; - if (hostname) - a->hostname = g_strdup(hostname); - a->port = port; - - purple_request_action(client->application, _("Key Agreement Request"), tmp, - hostname ? tmp2 : NULL, 1, purple_request_cpar_from_connection(gc), - a, 2, _("Yes"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb), - _("No"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb)); -} - -static void -silcpurple_buddy_keyagr(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *buddy; - PurpleAccount *account; - - buddy = (PurpleBuddy *)node; - account = purple_buddy_get_account(buddy); - silcpurple_buddy_keyagr_do(purple_account_get_connection(account), - purple_buddy_get_name(buddy), FALSE); -} - - -/**************************** Static IM Key **********************************/ - -static void -silcpurple_buddy_resetkey(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *b; - PurpleConnection *gc; - SilcPurple sg; - SilcDList clients; - - g_return_if_fail(PURPLE_IS_BUDDY(node)); - - b = (PurpleBuddy *) node; - gc = purple_account_get_connection(purple_buddy_get_account(b)); - sg = purple_connection_get_protocol_data(gc); - - /* Find client entry */ - clients = silc_client_get_clients_local(sg->client, sg->conn, - purple_buddy_get_name(b), FALSE); - if (!clients) - return; - - silc_dlist_start(clients); - silc_client_del_private_message_key(sg->client, sg->conn, - silc_dlist_get(clients)); - silc_client_list_free(sg->client, sg->conn, clients); -} - -typedef struct { - SilcClient client; - SilcClientConnection conn; - SilcClientID client_id; -} *SilcPurplePrivkey; - -static void -silcpurple_buddy_privkey(PurpleConnection *gc, const char *name); - -static void -silcpurple_buddy_privkey_cb(SilcPurplePrivkey p, const char *passphrase) -{ - SilcClientEntry client_entry; - - if (!passphrase || !(*passphrase)) { - silc_free(p); - return; - } - - /* Get the client entry. */ - client_entry = silc_client_get_client_by_id(p->client, p->conn, - &p->client_id); - if (!client_entry) { - purple_notify_error(p->client->application, _("IM With Password"), - _("The remote user is not present in the network any more"), - NULL, NULL); - silc_free(p); - return; - } - - /* Set the private message key */ - silc_client_del_private_message_key(p->client, p->conn, - client_entry); - silc_client_add_private_message_key(p->client, p->conn, - client_entry, NULL, NULL, - (unsigned char *)passphrase, - strlen(passphrase)); - silc_free(p); -} - -static void -silcpurple_buddy_privkey_resolved(SilcClient client, - SilcClientConnection conn, - SilcStatus status, - SilcDList clients, - void *context) -{ - char tmp[256]; - - if (!clients) { - g_snprintf(tmp, sizeof(tmp), - _("User %s is not present in the network"), - (const char *)context); - purple_notify_error(client->application, _("IM With Password"), - _("Cannot set IM key"), tmp, NULL); - g_free(context); - return; - } - - silcpurple_buddy_privkey(client->application, context); - g_free(context); -} - -static void -silcpurple_buddy_privkey(PurpleConnection *gc, const char *name) -{ - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcPurplePrivkey p; - SilcDList clients; - SilcClientEntry client_entry; - - if (!name) - return; - - /* Find client entry */ - clients = silc_client_get_clients_local(sg->client, sg->conn, - name, FALSE); - if (!clients) { - silc_client_get_clients(sg->client, sg->conn, name, NULL, - silcpurple_buddy_privkey_resolved, - g_strdup(name)); - return; - } - - silc_dlist_start(clients); - client_entry = silc_dlist_get(clients); - - p = silc_calloc(1, sizeof(*p)); - if (!p) - return; - p->client = sg->client; - p->conn = sg->conn; - p->client_id = client_entry->id; - purple_request_input(gc, _("IM With Password"), NULL, - _("Set IM Password"), NULL, FALSE, TRUE, NULL, - _("OK"), G_CALLBACK(silcpurple_buddy_privkey_cb), - _("Cancel"), G_CALLBACK(silcpurple_buddy_privkey_cb), - purple_request_cpar_from_connection(gc), p); - - silc_client_list_free(sg->client, sg->conn, clients); -} - -static void -silcpurple_buddy_privkey_menu(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *buddy; - PurpleConnection *gc; - - g_return_if_fail(PURPLE_IS_BUDDY(node)); - - buddy = (PurpleBuddy *) node; - gc = purple_account_get_connection(purple_buddy_get_account(buddy)); - - silcpurple_buddy_privkey(gc, purple_buddy_get_name(buddy)); -} - - -/**************************** Get Public Key *********************************/ - -typedef struct { - SilcClient client; - SilcClientConnection conn; - SilcClientID client_id; -} *SilcPurpleBuddyGetkey; - -static void -silcpurple_buddy_getkey(PurpleConnection *gc, const char *name); - -static SilcBool -silcpurple_buddy_getkey_cb(SilcClient client, SilcClientConnection conn, - SilcCommand command, SilcStatus status, - SilcStatus error, void *context, va_list ap) -{ - SilcClientEntry client_entry; - SilcPurpleBuddyGetkey g = context; - - if (status != SILC_STATUS_OK) { - purple_notify_error(g->client->application, _("Get Public Key"), - _("The remote user is not present in the network any more"), - NULL, NULL); - silc_free(g); - return FALSE; - } - - /* Get the client entry. */ - client_entry = silc_client_get_client_by_id(g->client, g->conn, - &g->client_id); - if (!client_entry) { - purple_notify_error(g->client->application, _("Get Public Key"), - _("The remote user is not present in the network any more"), - NULL, NULL); - silc_free(g); - return FALSE; - } - - if (!client_entry->public_key) { - silc_free(g); - return FALSE; - } - - /* Now verify the public key */ - silcpurple_verify_public_key(g->client, g->conn, client_entry->nickname, - SILC_CONN_CLIENT, client_entry->public_key, - NULL, NULL); - silc_free(g); - return TRUE; -} - -static void -silcpurple_buddy_getkey_resolved(SilcClient client, - SilcClientConnection conn, - SilcStatus status, - SilcDList clients, - void *context) -{ - char tmp[256]; - - if (!clients) { - g_snprintf(tmp, sizeof(tmp), - _("User %s is not present in the network"), - (const char *)context); - purple_notify_error(client->application, _("Get Public Key"), - _("Cannot fetch the public key"), tmp, NULL); - g_free(context); - return; - } - - silcpurple_buddy_getkey(client->application, context); - g_free(context); -} - -static void -silcpurple_buddy_getkey(PurpleConnection *gc, const char *name) -{ - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcClientEntry client_entry; - SilcDList clients; - SilcPurpleBuddyGetkey g; - SilcUInt16 cmd_ident; - - if (!name) - return; - - /* Find client entry */ - clients = silc_client_get_clients_local(client, conn, name, FALSE); - if (!clients) { - silc_client_get_clients(client, conn, name, NULL, - silcpurple_buddy_getkey_resolved, - g_strdup(name)); - return; - } - - silc_dlist_start(clients); - client_entry = silc_dlist_get(clients); - - /* Call GETKEY */ - g = silc_calloc(1, sizeof(*g)); - if (!g) - return; - g->client = client; - g->conn = conn; - g->client_id = client_entry->id; - cmd_ident = silc_client_command_call(client, conn, NULL, "GETKEY", - client_entry->nickname, NULL); - silc_client_command_pending(conn, SILC_COMMAND_GETKEY, cmd_ident, - silcpurple_buddy_getkey_cb, g); - silc_client_list_free(client, conn, clients); -} - -static void -silcpurple_buddy_getkey_menu(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *buddy; - PurpleConnection *gc; - - g_return_if_fail(PURPLE_IS_BUDDY(node)); - - buddy = (PurpleBuddy *) node; - gc = purple_account_get_connection(purple_buddy_get_account(buddy)); - - silcpurple_buddy_getkey(gc, purple_buddy_get_name(buddy)); -} - -static void -silcpurple_buddy_showkey(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *b; - PurpleConnection *gc; - SilcPurple sg; - SilcPublicKey public_key; - const char *pkfile; - - g_return_if_fail(PURPLE_IS_BUDDY(node)); - - b = (PurpleBuddy *) node; - gc = purple_account_get_connection(purple_buddy_get_account(b)); - sg = purple_connection_get_protocol_data(gc); - - pkfile = purple_blist_node_get_string(node, "public-key"); - if (!silc_pkcs_load_public_key(pkfile, &public_key)) { - purple_notify_error(gc, _("Show Public Key"), - _("Could not load public key"), NULL, - purple_request_cpar_from_connection(gc)); - return; - } - - silcpurple_show_public_key(sg, purple_buddy_get_name(b), public_key, NULL, NULL); - silc_pkcs_public_key_free(public_key); -} - - -/**************************** Buddy routines *********************************/ - -/* The buddies are implemented by using the WHOIS and WATCH commands that - can be used to search users by their public key. Since nicknames aren't - unique in SILC we cannot trust the buddy list using their nickname. We - associate public keys to buddies and use those to search and watch - in the network. - - The problem is that Purple does not return PurpleBuddy contexts to the - callbacks but the buddy names. Naturally, this is not going to work - with SILC. But, for now, we have to do what we can... */ - -typedef struct { - SilcClient client; - SilcClientConnection conn; - SilcClientID client_id; - PurpleBuddy *b; - unsigned char *offline_pk; - SilcUInt32 offline_pk_len; - SilcPublicKey public_key; - unsigned int offline : 1; - unsigned int pubkey_search : 1; - unsigned int init : 1; -} *SilcPurpleBuddyRes; - -static void -silcpurple_add_buddy_ask_pk_cb(SilcPurpleBuddyRes r, gint id); -static void -silcpurple_add_buddy_resolved(SilcClient client, - SilcClientConnection conn, - SilcStatus status, - SilcDList clients, - void *context); - -void silcpurple_get_info(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const char *who) -{ - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcClientEntry client_entry; - PurpleBuddy *b; - const char *filename, *nick = who; - char tmp[256]; - - if (!who) - return; - if (strlen(who) > 1 && who[0] == '@') - nick = who + 1; - if (strlen(who) > 1 && who[0] == '*') - nick = who + 1; - if (strlen(who) > 2 && who[0] == '*' && who[1] == '@') - nick = who + 2; - - b = purple_blist_find_buddy(purple_connection_get_account(gc), nick); - if (b) { - /* See if we have this buddy's public key. If we do use that - to search the details. */ - gpointer proto_data; - filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key"); - if (filename) { - /* Call WHOIS. The user info is displayed in the WHOIS - command reply. */ - silc_client_command_call(client, conn, NULL, "WHOIS", - "-details", "-pubkey", filename, NULL); - return; - } - - if (!(proto_data = purple_buddy_get_protocol_data(b))) { - g_snprintf(tmp, sizeof(tmp), - _("User %s is not present in the network"), purple_buddy_get_name(b)); - purple_notify_error(gc, _("User Information"), - _("Cannot get user information"), tmp, - purple_request_cpar_from_connection(gc)); - return; - } - - client_entry = silc_client_get_client_by_id(client, conn, proto_data); - if (client_entry) { - /* Call WHOIS. The user info is displayed in the WHOIS - command reply. */ - silc_client_command_call(client, conn, NULL, "WHOIS", - client_entry->nickname, "-details", NULL); - } - } else { - /* Call WHOIS just with nickname. */ - silc_client_command_call(client, conn, NULL, "WHOIS", nick, NULL); - } -} - -static void -silcpurple_add_buddy_pk_no(SilcPurpleBuddyRes r) -{ - char tmp[512]; - g_snprintf(tmp, sizeof(tmp), _("The %s buddy is not trusted"), - purple_buddy_get_name(r->b)); - purple_notify_error(r->client->application, _("Add Buddy"), tmp, - _("You cannot receive buddy notifications until you " - "import his/her public key. You can use the Get Public Key " - "command to get the public key."), - purple_request_cpar_from_account(purple_buddy_get_account(r->b))); - purple_protocol_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL); -} - -static void -silcpurple_add_buddy_save(SilcBool success, void *context) -{ - SilcPurpleBuddyRes r = context; - PurpleBuddy *b = r->b; - SilcClientEntry client_entry; - SilcAttributePayload attr; - SilcAttribute attribute; - SilcVCardStruct vcard; - SilcMime message = NULL, extension = NULL; - SilcMime usericon = NULL; - SilcAttributeObjPk serverpk, usersign, serversign; - gboolean usign_success = TRUE, ssign_success = TRUE; - char filename[512], filename2[512], *fingerprint = NULL, *tmp; - SilcUInt32 len; - SilcHash hash; - gsize i; - - if (!success) { - /* The user did not trust the public key. */ - silcpurple_add_buddy_pk_no(r); - silc_free(r->offline_pk); - if (r->public_key) - silc_pkcs_public_key_free(r->public_key); - silc_free(r); - return; - } - - if (r->offline) { - /* User is offline. Associate the imported public key with - this user. */ - fingerprint = silc_hash_fingerprint(NULL, r->offline_pk, - r->offline_pk_len); - for (i = 0; i < strlen(fingerprint); i++) - if (fingerprint[i] == ' ') - fingerprint[i] = '_'; - g_snprintf(filename, sizeof(filename) - 1, - "%s" G_DIR_SEPARATOR_S "clientkeys" G_DIR_SEPARATOR_S "clientkey_%s.pub", - silcpurple_silcdir(), fingerprint); - purple_blist_node_set_string((PurpleBlistNode *)b, "public-key", filename); - purple_protocol_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL); - silc_free(fingerprint); - silc_free(r->offline_pk); - if (r->public_key) - silc_pkcs_public_key_free(r->public_key); - silc_free(r); - return; - } - - /* Get the client entry. */ - client_entry = silc_client_get_client_by_id(r->client, r->conn, - &r->client_id); - if (!client_entry) { - silc_free(r->offline_pk); - silc_pkcs_public_key_free(r->public_key); - if (r->public_key) - silc_pkcs_public_key_free(r->public_key); - silc_free(r); - return; - } - - memset(&vcard, 0, sizeof(vcard)); - memset(&serverpk, 0, sizeof(serverpk)); - memset(&usersign, 0, sizeof(usersign)); - memset(&serversign, 0, sizeof(serversign)); - - /* Now that we have the public key and we trust it now we - save the attributes of the buddy and update its status. */ - - if (client_entry->attrs) { - silc_dlist_start(client_entry->attrs); - while ((attr = silc_dlist_get(client_entry->attrs)) - != SILC_LIST_END) { - attribute = silc_attribute_get_attribute(attr); - - switch (attribute) { - case SILC_ATTRIBUTE_USER_INFO: - if (!silc_attribute_get_object(attr, (void *)&vcard, - sizeof(vcard))) - continue; - break; - - case SILC_ATTRIBUTE_STATUS_MESSAGE: - message = silc_mime_alloc(); - if (!silc_attribute_get_object(attr, (void *)message, - sizeof(*message))) - continue; - break; - - case SILC_ATTRIBUTE_EXTENSION: - extension = silc_mime_alloc(); - if (!silc_attribute_get_object(attr, (void *)extension, - sizeof(*extension))) - continue; - break; - - case SILC_ATTRIBUTE_USER_ICON: - usericon = silc_mime_alloc(); - if (!silc_attribute_get_object(attr, (void *)usericon, - sizeof(*usericon))) - 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; - } - } - } - - /* Verify the attribute signatures */ - silc_hash_alloc((const unsigned char *)"sha1", &hash); - - if (usersign.data) { - unsigned char *verifyd; - SilcUInt32 verify_len; - - verifyd = silc_attribute_get_verify_data(client_entry->attrs, - FALSE, &verify_len); - if (verifyd && !silc_pkcs_verify(client_entry->public_key, - usersign.data, - usersign.data_len, - verifyd, verify_len, hash)) - usign_success = FALSE; - silc_free(verifyd); - } - - if (serversign.data) { - SilcPublicKey public_key; - SilcPKCSType type = 0; - unsigned char *verifyd; - SilcUInt32 verify_len; - - if (purple_strequal(serverpk.type, "silc-rsa")) - type = SILC_PKCS_SILC; - else if (purple_strequal(serverpk.type, "ssh-rsa")) - type = SILC_PKCS_SSH2; - else if (purple_strequal(serverpk.type, "x509v3-sign-rsa")) - type = SILC_PKCS_X509V3; - else if (purple_strequal(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(client_entry->attrs, - TRUE, &verify_len); - if (verifyd && !silc_pkcs_verify(public_key, - serversign.data, - serversign.data_len, - verifyd, verify_len, - hash)) - ssign_success = FALSE; - silc_pkcs_public_key_free(public_key); - silc_free(verifyd); - } - } - - fingerprint = silc_fingerprint(client_entry->fingerprint, 20); - for (i = 0; i < strlen(fingerprint); i++) - if (fingerprint[i] == ' ') - fingerprint[i] = '_'; - - if (usign_success || ssign_success) { - struct passwd *pw; - - memset(filename2, 0, sizeof(filename2)); - - /* Filename for dir */ - tmp = fingerprint + strlen(fingerprint) - 9; - g_snprintf(filename, sizeof(filename) - 1, - "%s" G_DIR_SEPARATOR_S "friends" G_DIR_SEPARATOR_S "%s", - silcpurple_silcdir(), tmp); - - pw = getpwuid(getuid()); - if (!pw) - return; - - /* Create dir if it doesn't exist */ - if (pw->pw_uid == geteuid()) { - if (g_mkdir(filename, 0755) != 0 && errno != EEXIST) - return; - } - - /* Save VCard */ - g_snprintf(filename2, sizeof(filename2) - 1, - "%s" G_DIR_SEPARATOR_S "vcard", filename); - if (vcard.full_name) { - tmp = (char *)silc_vcard_encode(&vcard, &len); - silc_file_writefile(filename2, tmp, len); - silc_free(tmp); - } - - /* Save status message */ - if (message) { - memset(filename2, 0, sizeof(filename2)); - g_snprintf(filename2, sizeof(filename2) - 1, - "%s" G_DIR_SEPARATOR_S "status_message.mime", - filename); - tmp = (char *)silc_mime_get_data(message, &len); - silc_file_writefile(filename2, tmp, len); - silc_mime_free(message); - } - - /* Save extension data */ - if (extension) { - memset(filename2, 0, sizeof(filename2)); - g_snprintf(filename2, sizeof(filename2) - 1, - "%s" G_DIR_SEPARATOR_S "extension.mime", - filename); - tmp = (char *)silc_mime_get_data(extension, &len); - silc_file_writefile(filename2, tmp, len); - silc_mime_free(extension); - } - - /* Save user icon */ - if (usericon) { - const char *type = silc_mime_get_field(usericon, "Content-Type"); - if (type && - (purple_strequal(type, "image/jpeg") || - purple_strequal(type, "image/gif") || - purple_strequal(type, "image/bmp") || - purple_strequal(type, "image/png"))) { - const unsigned char *data; - SilcUInt32 data_len; - data = silc_mime_get_data(usericon, &data_len); - if (data) { - /* TODO: Check if SILC gives us something to use as the checksum instead */ - purple_buddy_icons_set_for_user(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), g_memdup2(data, data_len), data_len, NULL); - } - } - silc_mime_free(usericon); - } - } - - /* Save the public key path to buddy properties, as it is used - to identify the buddy in the network (and not the nickname). */ - memset(filename, 0, sizeof(filename)); - g_snprintf(filename, sizeof(filename) - 1, - "%s" G_DIR_SEPARATOR_S "clientkeys" G_DIR_SEPARATOR_S "clientkey_%s.pub", - silcpurple_silcdir(), fingerprint); - purple_blist_node_set_string((PurpleBlistNode *)b, "public-key", filename); - - /* Update online status */ - purple_protocol_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL); - - /* Finally, start watching this user so we receive its status - changes from the server */ - g_snprintf(filename2, sizeof(filename2) - 1, "+%s", filename); - silc_client_command_call(r->client, r->conn, NULL, "WATCH", "-pubkey", - filename2, NULL); - - silc_hash_free(hash); - silc_free(fingerprint); - silc_free(r->offline_pk); - if (r->public_key) - silc_pkcs_public_key_free(r->public_key); - silc_free(r); -} - -static void -silcpurple_add_buddy_ask_import(void *user_data, const char *name) -{ - SilcPurpleBuddyRes r = (SilcPurpleBuddyRes)user_data; - - /* Load the public key */ - if (!silc_pkcs_load_public_key(name, &r->public_key)) { - silcpurple_add_buddy_ask_pk_cb(r, 0); - purple_notify_error(r->client->application, _("Add Buddy"), - _("Could not load public key"), NULL, - purple_request_cpar_from_account( - purple_buddy_get_account(r->b))); - return; - } - - /* Now verify the public key */ - r->offline_pk = silc_pkcs_public_key_encode(r->public_key, &r->offline_pk_len); - silcpurple_verify_public_key(r->client, r->conn, purple_buddy_get_name(r->b), - SILC_CONN_CLIENT, r->public_key, - silcpurple_add_buddy_save, r); -} - -static void -silcpurple_add_buddy_ask_pk_cancel(void *user_data, const char *name) -{ - SilcPurpleBuddyRes r = (SilcPurpleBuddyRes)user_data; - - /* The user did not import public key. The buddy is unusable. */ - silcpurple_add_buddy_pk_no(r); - silc_free(r); -} - -static void -silcpurple_add_buddy_ask_pk_cb(SilcPurpleBuddyRes r, gint id) -{ - if (id != 0) { - /* The user did not import public key. The buddy is unusable. */ - silcpurple_add_buddy_pk_no(r); - silc_free(r); - return; - } - - /* Open file selector to select the public key. */ - purple_request_file(r->client->application, _("Open..."), NULL, FALSE, - G_CALLBACK(silcpurple_add_buddy_ask_import), - G_CALLBACK(silcpurple_add_buddy_ask_pk_cancel), - purple_request_cpar_from_account(purple_buddy_get_account(r->b)), r); - -} - -static void -silcpurple_add_buddy_ask_pk(SilcPurpleBuddyRes r) -{ - char tmp[512]; - g_snprintf(tmp, sizeof(tmp), _("The %s buddy is not present in the network"), - purple_buddy_get_name(r->b)); - purple_request_action(r->client->application, _("Add Buddy"), tmp, - _("To add the buddy you must import his/her public key. " - "Press Import to import a public key."), 0, - purple_request_cpar_from_account(purple_buddy_get_account(r->b)), r, 2, - _("Cancel"), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb), - _("_Import..."), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb)); -} - -static SilcBool -silcpurple_add_buddy_getkey_cb(SilcClient client, SilcClientConnection conn, - SilcCommand command, SilcStatus status, - SilcStatus error, void *context, va_list ap) -{ - SilcPurpleBuddyRes r = context; - SilcClientEntry client_entry; - - if (status != SILC_STATUS_OK) { - /* The buddy is offline/nonexistent. We will require user - to associate a public key with the buddy or the buddy - cannot be added. */ - r->offline = TRUE; - silcpurple_add_buddy_ask_pk(r); - return FALSE; - } - - /* Get the client entry. */ - client_entry = silc_client_get_client_by_id(r->client, r->conn, - &r->client_id); - if (!client_entry || !client_entry->public_key) { - /* The buddy is offline/nonexistent. We will require user - to associate a public key with the buddy or the buddy - cannot be added. */ - r->offline = TRUE; - silcpurple_add_buddy_ask_pk(r); - return FALSE; - } - - /* Now verify the public key */ - silcpurple_verify_public_key(r->client, r->conn, client_entry->nickname, - SILC_CONN_CLIENT, client_entry->public_key, - silcpurple_add_buddy_save, r); - return TRUE; -} - -static void -silcpurple_add_buddy_select_cb(SilcPurpleBuddyRes r, PurpleRequestFields *fields) -{ - PurpleRequestField *f; - GList *list; - SilcClientEntry client_entry; - SilcDList clients; - - f = purple_request_fields_get_field(fields, "list"); - list = purple_request_field_list_get_selected(f); - if (!list) { - /* The user did not select any user. */ - silcpurple_add_buddy_pk_no(r); - silc_free(r); - return; - } - - client_entry = purple_request_field_list_get_data(f, list->data); - clients = silc_dlist_init(); - silc_dlist_add(clients, client_entry); - silcpurple_add_buddy_resolved(r->client, r->conn, SILC_STATUS_OK, - clients, r); - silc_dlist_uninit(clients); -} - -static void -silcpurple_add_buddy_select_cancel(SilcPurpleBuddyRes r, PurpleRequestFields *fields) -{ - /* The user did not select any user. */ - silcpurple_add_buddy_pk_no(r); - silc_free(r); -} - -static void -silcpurple_add_buddy_select(SilcPurpleBuddyRes r, SilcDList clients) -{ - PurpleRequestFields *fields; - PurpleRequestFieldGroup *g; - PurpleRequestField *f; - char tmp[512], tmp2[128]; - char *fingerprint; - SilcClientEntry client_entry; - - fields = purple_request_fields_new(); - g = purple_request_field_group_new(NULL); - f = purple_request_field_list_new("list", NULL); - purple_request_field_group_add_field(g, f); - purple_request_field_list_set_multi_select(f, FALSE); - purple_request_fields_add_group(fields, g); - - silc_dlist_start(clients); - while ((client_entry = silc_dlist_get(clients))) { - fingerprint = NULL; - if (*client_entry->fingerprint) { - fingerprint = silc_fingerprint(client_entry->fingerprint, 20); - g_snprintf(tmp2, sizeof(tmp2), "\n%s", fingerprint); - } - g_snprintf(tmp, sizeof(tmp), "%s - %s (%s@%s)%s", - client_entry->realname, client_entry->nickname, - client_entry->username, *client_entry->hostname ? - client_entry->hostname : "", - fingerprint ? tmp2 : ""); - purple_request_field_list_add_icon(f, tmp, NULL, client_entry); - silc_free(fingerprint); - } - - purple_request_fields(r->client->application, _("Add Buddy"), - _("Select correct user"), - r->pubkey_search - ? _("More than one user was found with the same public key. Select " - "the correct user from the list to add to the buddy list.") - : _("More than one user was found with the same name. Select " - "the correct user from the list to add to the buddy list."), - fields, - _("OK"), G_CALLBACK(silcpurple_add_buddy_select_cb), - _("Cancel"), G_CALLBACK(silcpurple_add_buddy_select_cancel), - purple_request_cpar_from_account(purple_buddy_get_account(r->b)), r); -} - -static void -silcpurple_add_buddy_resolved(SilcClient client, - SilcClientConnection conn, - SilcStatus status, - SilcDList clients, - void *context) -{ - SilcPurpleBuddyRes r = context; - PurpleBuddy *b = r->b; - SilcAttributePayload pub; - SilcAttributeObjPk userpk; - const char *filename; - SilcClientEntry client_entry = NULL; - SilcUInt16 cmd_ident; - const char *name; - - filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key"); - - /* If the buddy is offline/nonexistent, we will require user - to associate a public key with the buddy or the buddy - cannot be added. */ - if (!clients) { - if (r->init) { - silc_free(r); - return; - } - - r->offline = TRUE; - /* If the user has already associated a public key, try loading it - * before prompting the user to load it again */ - if (filename != NULL) - silcpurple_add_buddy_ask_import(r, filename); - else - silcpurple_add_buddy_ask_pk(r); - return; - } - - /* If more than one client was found with nickname, we need to verify - from user which one is the correct. */ - if (silc_dlist_count(clients) > 1 && !r->pubkey_search) { - if (r->init) { - silc_free(r); - return; - } - - silcpurple_add_buddy_select(r, clients); - return; - } - - silc_dlist_start(clients); - client_entry = silc_dlist_get(clients); - - name = purple_buddy_get_name(b); - - /* If we searched using public keys and more than one entry was found - the same person is logged on multiple times. */ - if (silc_dlist_count(clients) > 1 && r->pubkey_search && name) { - if (r->init) { - /* Find the entry that closest matches to the - buddy nickname. */ - SilcClientEntry entry; - silc_dlist_start(clients); - while ((entry = silc_dlist_get(clients))) { - if (!g_ascii_strncasecmp(name, entry->nickname, - strlen(name))) { - client_entry = entry; - break; - } - } - } else { - /* Verify from user which one is correct */ - silcpurple_add_buddy_select(r, clients); - return; - } - } - - g_return_if_fail(client_entry != NULL); - - /* The client was found. Now get its public key and verify - that before adding the buddy. */ - memset(&userpk, 0, sizeof(userpk)); - purple_buddy_set_protocol_data(b, silc_memdup(&client_entry->id, sizeof(client_entry->id))); - r->client_id = client_entry->id; - - /* Get the public key from attributes, if not present then - resolve it with GETKEY unless we have it cached already. */ - if (client_entry->attrs && !client_entry->public_key) { - pub = silcpurple_get_attr(client_entry->attrs, - SILC_ATTRIBUTE_USER_PUBLIC_KEY); - if (!pub || !silc_attribute_get_object(pub, (void *)&userpk, - sizeof(userpk))) { - /* Get public key with GETKEY */ - cmd_ident = - silc_client_command_call(client, conn, NULL, - "GETKEY", client_entry->nickname, NULL); - silc_client_command_pending(conn, SILC_COMMAND_GETKEY, - cmd_ident, - silcpurple_add_buddy_getkey_cb, - r); - return; - } - if (!silc_pkcs_public_key_alloc(SILC_PKCS_SILC, - userpk.data, userpk.data_len, - &client_entry->public_key)) - return; - silc_free(userpk.data); - } else if (filename && !client_entry->public_key) { - if (!silc_pkcs_load_public_key(filename, &client_entry->public_key)) { - /* Get public key with GETKEY */ - cmd_ident = - silc_client_command_call(client, conn, NULL, - "GETKEY", client_entry->nickname, NULL); - silc_client_command_pending(conn, SILC_COMMAND_GETKEY, - cmd_ident, - silcpurple_add_buddy_getkey_cb, - r); - return; - } - } else if (!client_entry->public_key) { - /* Get public key with GETKEY */ - cmd_ident = - silc_client_command_call(client, conn, NULL, - "GETKEY", client_entry->nickname, NULL); - silc_client_command_pending(conn, SILC_COMMAND_GETKEY, - cmd_ident, - silcpurple_add_buddy_getkey_cb, - r); - return; - } - - /* We have the public key, verify it. */ - silcpurple_verify_public_key(client, conn, client_entry->nickname, - SILC_CONN_CLIENT, - client_entry->public_key, - silcpurple_add_buddy_save, r); -} - -static void -silcpurple_add_buddy_i(PurpleConnection *gc, PurpleBuddy *b, gboolean init) -{ - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcPurpleBuddyRes r; - SilcBuffer attrs; - const char *filename, *name = purple_buddy_get_name(b); - - r = silc_calloc(1, sizeof(*r)); - if (!r) - return; - r->client = client; - r->conn = conn; - r->b = b; - r->init = init; - - /* See if we have this buddy's public key. If we do use that - to search the details. */ - filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key"); - if (filename) { - SilcPublicKey public_key; - SilcAttributeObjPk userpk; - - if (!silc_pkcs_load_public_key(filename, &public_key)) - return; - - /* Get all attributes, and use the public key to search user */ - name = NULL; - attrs = silc_client_attributes_request(SILC_ATTRIBUTE_USER_INFO, - SILC_ATTRIBUTE_SERVICE, - SILC_ATTRIBUTE_STATUS_MOOD, - SILC_ATTRIBUTE_STATUS_FREETEXT, - SILC_ATTRIBUTE_STATUS_MESSAGE, - SILC_ATTRIBUTE_PREFERRED_LANGUAGE, - SILC_ATTRIBUTE_PREFERRED_CONTACT, - SILC_ATTRIBUTE_TIMEZONE, - SILC_ATTRIBUTE_GEOLOCATION, - SILC_ATTRIBUTE_USER_ICON, - SILC_ATTRIBUTE_DEVICE_INFO, 0); - userpk.type = "silc-rsa"; - userpk.data = silc_pkcs_public_key_encode(public_key, &userpk.data_len); - attrs = silc_attribute_payload_encode(attrs, - SILC_ATTRIBUTE_USER_PUBLIC_KEY, - SILC_ATTRIBUTE_FLAG_VALID, - &userpk, sizeof(userpk)); - silc_free(userpk.data); - silc_pkcs_public_key_free(public_key); - r->pubkey_search = TRUE; - } else { - /* Get all attributes */ - attrs = silc_client_attributes_request(0); - } - - /* Resolve */ - silc_client_get_clients_whois(client, conn, name, NULL, attrs, - silcpurple_add_buddy_resolved, r); - silc_buffer_free(attrs); -} - -void silcpurple_add_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *message) -{ - /* Don't add if the buddy is already on the list. - * - * SILC doesn't have groups, so we also don't need to do anything - * for a move. */ - if (purple_buddy_get_protocol_data(buddy) == NULL) - silcpurple_add_buddy_i(gc, buddy, FALSE); -} - -void silcpurple_send_buddylist(PurpleConnection *gc) -{ - GSList *buddies; - PurpleAccount *account; - - account = purple_connection_get_account(gc); - - for (buddies = purple_blist_find_buddies(account, NULL); buddies; - buddies = g_slist_delete_link(buddies, buddies)) - { - PurpleBuddy *buddy = buddies->data; - silcpurple_add_buddy_i(gc, buddy, TRUE); - } -} - -void silcpurple_remove_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleBuddy *buddy, - PurpleGroup *group) -{ - silc_free(purple_buddy_get_protocol_data(buddy)); -} - -void silcpurple_idle_set(PurpleProtocolServer *protocol_server, PurpleConnection *gc, int idle) - -{ - SilcPurple sg; - SilcClient client; - SilcClientConnection conn; - SilcAttributeObjService service; - const char *server; - int port; - - sg = purple_connection_get_protocol_data(gc); - if (sg == NULL) - return; - - client = sg->client; - if (client == NULL) - return; - - conn = sg->conn; - if (conn == NULL) - return; - - server = purple_account_get_string(sg->account, "server", - "silc.silcnet.org"); - port = purple_account_get_int(sg->account, "port", 706), - - memset(&service, 0, sizeof(service)); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_SERVICE, NULL); - service.port = port; - g_snprintf(service.address, sizeof(service.address), "%s", server); - service.idle = idle; - silc_client_attribute_add(client, conn, SILC_ATTRIBUTE_SERVICE, - &service, sizeof(service)); -} - -char *silcpurple_status_text(PurpleProtocolClient *ppclient, PurpleBuddy *b) -{ - PurpleAccount *account = purple_buddy_get_account(b); - PurpleConnection *gc = purple_account_get_connection(account); - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcClientID *client_id = purple_buddy_get_protocol_data(b); - SilcClientEntry client_entry; - SilcAttributePayload attr; - SilcAttributeMood mood = 0; - - /* Get the client entry. */ - client_entry = silc_client_get_client_by_id(client, conn, client_id); - if (!client_entry) - return NULL; - - /* If user is online, we show the mood status, if available. - If user is offline or away that status is indicated. */ - - if (client_entry->mode & SILC_UMODE_DETACHED) - return g_strdup(_("Detached")); - if (client_entry->mode & SILC_UMODE_GONE) - return g_strdup(_("Away")); - if (client_entry->mode & SILC_UMODE_INDISPOSED) - return g_strdup(_("Indisposed")); - if (client_entry->mode & SILC_UMODE_BUSY) - return g_strdup(_("Busy")); - if (client_entry->mode & SILC_UMODE_PAGE) - return g_strdup(_("Wake Me Up")); - if (client_entry->mode & SILC_UMODE_HYPER) - return g_strdup(_("Hyper Active")); - if (client_entry->mode & SILC_UMODE_ROBOT) - return g_strdup(_("Robot")); - - attr = silcpurple_get_attr(client_entry->attrs, SILC_ATTRIBUTE_STATUS_MOOD); - if (attr && silc_attribute_get_object(attr, &mood, sizeof(mood))) { - /* The mood is a bit mask, so we could show multiple moods, - but let's show only one for now. */ - if (mood & SILC_ATTRIBUTE_MOOD_HAPPY) - return g_strdup(_("Happy")); - if (mood & SILC_ATTRIBUTE_MOOD_SAD) - return g_strdup(_("Sad")); - if (mood & SILC_ATTRIBUTE_MOOD_ANGRY) - return g_strdup(_("Angry")); - if (mood & SILC_ATTRIBUTE_MOOD_JEALOUS) - return g_strdup(_("Jealous")); - if (mood & SILC_ATTRIBUTE_MOOD_ASHAMED) - return g_strdup(_("Ashamed")); - if (mood & SILC_ATTRIBUTE_MOOD_INVINCIBLE) - return g_strdup(_("Invincible")); - if (mood & SILC_ATTRIBUTE_MOOD_INLOVE) - return g_strdup(_("In Love")); - if (mood & SILC_ATTRIBUTE_MOOD_SLEEPY) - return g_strdup(_("Sleepy")); - if (mood & SILC_ATTRIBUTE_MOOD_BORED) - return g_strdup(_("Bored")); - if (mood & SILC_ATTRIBUTE_MOOD_EXCITED) - return g_strdup(_("Excited")); - if (mood & SILC_ATTRIBUTE_MOOD_ANXIOUS) - return g_strdup(_("Anxious")); - } - - return NULL; -} - -void silcpurple_tooltip_text(PurpleProtocolClient *ppclient, PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) -{ - PurpleAccount *account = purple_buddy_get_account(b); - PurpleConnection *gc = purple_account_get_connection(account); - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcClientID *client_id = purple_buddy_get_protocol_data(b); - SilcClientEntry client_entry; - char *moodstr, *statusstr, *contactstr, *langstr, *devicestr, *tzstr, *geostr; - char tmp[256]; - - /* Get the client entry. */ - client_entry = silc_client_get_client_by_id(client, conn, client_id); - if (!client_entry) - return; - - /* TODO: Check whether it's correct to call add_pair_html, - or if we should be using add_pair_plaintext */ - purple_notify_user_info_add_pair_html(user_info, _("Nickname"), client_entry->nickname); - g_snprintf(tmp, sizeof(tmp), "%s@%s", client_entry->username, client_entry->hostname); - /* TODO: Check whether it's correct to call add_pair_html, - or if we should be using add_pair_plaintext */ - purple_notify_user_info_add_pair_html(user_info, _("Username"), tmp); - if (client_entry->mode) { - memset(tmp, 0, sizeof(tmp)); - silcpurple_get_umode_string(client_entry->mode, - tmp, sizeof(tmp) - strlen(tmp)); - purple_notify_user_info_add_pair_plaintext(user_info, _("User Modes"), tmp); - } - - silcpurple_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr); - - if (statusstr) { - /* TODO: Check whether it's correct to call add_pair_html, - or if we should be using add_pair_plaintext */ - purple_notify_user_info_add_pair_html(user_info, _("Message"), statusstr); - g_free(statusstr); - } - - if (full) { - if (moodstr) { - /* TODO: Check whether it's correct to call add_pair_html, - or if we should be using add_pair_plaintext */ - purple_notify_user_info_add_pair_html(user_info, _("Mood"), moodstr); - g_free(moodstr); - } - - if (contactstr) { - /* TODO: Check whether it's correct to call add_pair_html, - or if we should be using add_pair_plaintext */ - purple_notify_user_info_add_pair_html(user_info, _("Preferred Contact"), contactstr); - g_free(contactstr); - } - - if (langstr) { - /* TODO: Check whether it's correct to call add_pair_html, - or if we should be using add_pair_plaintext */ - purple_notify_user_info_add_pair_html(user_info, _("Preferred Language"), langstr); - g_free(langstr); - } - - if (devicestr) { - /* TODO: Check whether it's correct to call add_pair_html, - or if we should be using add_pair_plaintext */ - purple_notify_user_info_add_pair_html(user_info, _("Device"), devicestr); - g_free(devicestr); - } - - if (tzstr) { - /* TODO: Check whether it's correct to call add_pair_html, - or if we should be using add_pair_plaintext */ - purple_notify_user_info_add_pair_html(user_info, _("Timezone"), tzstr); - g_free(tzstr); - } - - if (geostr) { - /* TODO: Check whether it's correct to call add_pair_html, - or if we should be using add_pair_plaintext */ - purple_notify_user_info_add_pair_html(user_info, _("Geolocation"), geostr); - g_free(geostr); - } - } -} - -static void -silcpurple_buddy_kill(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *b; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_IS_BUDDY(node)); - - b = (PurpleBuddy *) node; - gc = purple_account_get_connection(purple_buddy_get_account(b)); - sg = purple_connection_get_protocol_data(gc); - - /* Call KILL */ - silc_client_command_call(sg->client, sg->conn, NULL, "KILL", - purple_buddy_get_name(b), "Killed by operator", NULL); -} - -typedef struct { - SilcPurple sg; - SilcClientEntry client_entry; -} *SilcPurpleBuddyWb; - -static void -silcpurple_buddy_wb(PurpleBlistNode *node, gpointer data) -{ - SilcPurpleBuddyWb wb = data; - silcpurple_wb_init(wb->sg, wb->client_entry); - silc_free(wb); -} - -GList *silcpurple_buddy_menu(PurpleBuddy *buddy) -{ - PurpleAccount *account = purple_buddy_get_account(buddy); - PurpleConnection *gc = purple_account_get_connection(account); - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcClientConnection conn = sg->conn; - const char *pkfile = NULL; - SilcClientEntry client_entry = NULL; - PurpleActionMenu *act; - GList *m = NULL; - SilcPurpleBuddyWb wb; - - pkfile = purple_blist_node_get_string((PurpleBlistNode *) buddy, "public-key"); - client_entry = silc_client_get_client_by_id(sg->client, - sg->conn, - purple_buddy_get_protocol_data(buddy)); - - if (client_entry && - silc_client_private_message_key_is_set(sg->client, - sg->conn, client_entry)) { - act = purple_action_menu_new(_("Reset IM Key"), - G_CALLBACK(silcpurple_buddy_resetkey), - NULL, NULL); - m = g_list_append(m, act); - } else { - act = purple_action_menu_new(_("IM with Key Exchange"), - G_CALLBACK(silcpurple_buddy_keyagr), - NULL, NULL); - m = g_list_append(m, act); - - act = purple_action_menu_new(_("IM with Password"), - G_CALLBACK(silcpurple_buddy_privkey_menu), - NULL, NULL); - m = g_list_append(m, act); - } - - if (pkfile) { - act = purple_action_menu_new(_("Show Public Key"), - G_CALLBACK(silcpurple_buddy_showkey), - NULL, NULL); - m = g_list_append(m, act); - - } else { - act = purple_action_menu_new(_("Get Public Key..."), - G_CALLBACK(silcpurple_buddy_getkey_menu), - NULL, NULL); - m = g_list_append(m, act); - } - - if (conn && conn->local_entry->mode & SILC_UMODE_ROUTER_OPERATOR) { - act = purple_action_menu_new(_("Kill User"), - G_CALLBACK(silcpurple_buddy_kill), - NULL, NULL); - m = g_list_append(m, act); - } - - if (client_entry) { - wb = silc_calloc(1, sizeof(*wb)); - wb->sg = sg; - wb->client_entry = client_entry; - act = purple_action_menu_new(_("Draw On Whiteboard"), - G_CALLBACK(silcpurple_buddy_wb), - (void *)wb, NULL); - m = g_list_append(m, act); - } - return m; -} - -void silcpurple_buddy_set_icon(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleImage *img) -{ - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcMime mime; - const gchar *type; - - /* Remove */ - if (!img) { - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_USER_ICON, NULL); - return; - } - - type = purple_image_get_mimetype(img); - if (type == NULL) - return; - if (purple_strequal(purple_image_get_extension(img), "ico")) - return; - - /* Add */ - mime = silc_mime_alloc(); - if (!mime) - return; - - silc_mime_add_field(mime, "Content-Type", type); - silc_mime_add_data(mime, purple_image_get_data(img), - purple_image_get_data_size(img)); - - silc_client_attribute_add(client, conn, SILC_ATTRIBUTE_USER_ICON, - mime, sizeof(*mime)); - - silc_mime_free(mime); -} diff --git a/libpurple/protocols/silc/chat.c b/libpurple/protocols/silc/chat.c deleted file mode 100644 index d05ef48ae3..0000000000 --- a/libpurple/protocols/silc/chat.c +++ /dev/null @@ -1,1376 +0,0 @@ -/* - - silcpurple_chat.c - - Author: Pekka Riikonen <priikone@silcnet.org> - - Copyright (C) 2004 - 2007 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. - -*/ - -#include <glib/gi18n-lib.h> - -#include "silcpurple.h" -#include "wb.h" - -/***************************** Channel Routines ******************************/ - -GList *silcpurple_chat_info(PurpleProtocolChat *protocol_chat, PurpleConnection *gc) -{ - GList *ci = NULL; - PurpleProtocolChatEntry *pce; - - pce = g_new0(PurpleProtocolChatEntry, 1); - pce->label = _("_Channel:"); - pce->identifier = "channel"; - pce->required = TRUE; - ci = g_list_append(ci, pce); - - pce = g_new0(PurpleProtocolChatEntry, 1); - pce->label = _("_Passphrase:"); - pce->identifier = "passphrase"; - pce->secret = TRUE; - ci = g_list_append(ci, pce); - - return ci; -} - -GHashTable *silcpurple_chat_info_defaults(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, const char *chat_name) -{ - GHashTable *defaults; - - defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); - - if (chat_name != NULL) - g_hash_table_insert(defaults, "channel", g_strdup(chat_name)); - - return defaults; -} - -static void -silcpurple_chat_getinfo(PurpleConnection *gc, GHashTable *components); - -static void -silcpurple_chat_getinfo_res(SilcClient client, - SilcClientConnection conn, - SilcStatus status, - SilcDList channels, - void *context) -{ - GHashTable *components = context; - PurpleConnection *gc = client->application; - const char *chname; - char tmp[256]; - - chname = g_hash_table_lookup(components, "channel"); - if (!chname) - return; - - if (!channels) { - g_snprintf(tmp, sizeof(tmp), - _("Channel %s does not exist in the network"), chname); - purple_notify_error(gc, _("Channel Information"), - _("Cannot get channel information"), tmp, - purple_request_cpar_from_connection(gc)); - return; - } - - silcpurple_chat_getinfo(gc, components); -} - - -static void -silcpurple_chat_getinfo(PurpleConnection *gc, GHashTable *components) -{ - SilcPurple sg = purple_connection_get_protocol_data(gc); - const char *chname; - char tmp[256], *tmp2; - GString *s; - SilcChannelEntry channel; - SilcHashTableList htl; - SilcChannelUser chu; - - if (!components) - return; - - chname = g_hash_table_lookup(components, "channel"); - if (!chname) - return; - channel = silc_client_get_channel(sg->client, sg->conn, - (char *)chname); - if (!channel) { - silc_client_get_channel_resolve(sg->client, sg->conn, - (char *)chname, - silcpurple_chat_getinfo_res, - components); - return; - } - - s = g_string_new(""); - tmp2 = g_markup_escape_text(channel->channel_name, -1); - g_string_append_printf(s, _("<b>Channel Name:</b> %s"), tmp2); - g_free(tmp2); - if (channel->user_list && silc_hash_table_count(channel->user_list)) - g_string_append_printf(s, _("<br><b>User Count:</b> %d"), - (int)silc_hash_table_count(channel->user_list)); - - silc_hash_table_list(channel->user_list, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) { - tmp2 = g_markup_escape_text(chu->client->nickname, -1); - g_string_append_printf(s, _("<br><b>Channel Founder:</b> %s"), - tmp2); - g_free(tmp2); - break; - } - } - silc_hash_table_list_reset(&htl); - - if (channel->cipher) - g_string_append_printf(s, _("<br><b>Channel Cipher:</b> %s"), - channel->cipher); - - if (channel->hmac) - /* Definition of HMAC: http://en.wikipedia.org/wiki/HMAC */ - g_string_append_printf(s, _("<br><b>Channel HMAC:</b> %s"), - channel->hmac); - - if (channel->topic) { - tmp2 = g_markup_escape_text(channel->topic, -1); - g_string_append_printf(s, _("<br><b>Channel Topic:</b><br>%s"), tmp2); - g_free(tmp2); - } - - if (channel->mode) { - g_string_append(s, _("<br><b>Channel Modes:</b> ")); - silcpurple_get_chmode_string(channel->mode, tmp, sizeof(tmp)); - g_string_append(s, tmp); - } - - if (channel->founder_key) { - char *fingerprint, *babbleprint; - unsigned char *pk; - SilcUInt32 pk_len; - pk = silc_pkcs_public_key_encode(channel->founder_key, &pk_len); - if (pk) { - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - - g_string_append_printf(s, _("<br><b>Founder Key Fingerprint:</b><br>%s"), fingerprint); - g_string_append_printf(s, _("<br><b>Founder Key Babbleprint:</b><br>%s"), babbleprint); - - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); - } - } - - purple_notify_formatted(gc, NULL, _("Channel Information"), NULL, s->str, NULL, NULL); - g_string_free(s, TRUE); -} - - -static void -silcpurple_chat_getinfo_menu(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat = (PurpleChat *)node; - PurpleAccount *account = purple_chat_get_account(chat); - silcpurple_chat_getinfo(purple_account_get_connection(account), - purple_chat_get_components(chat)); -} - - -/************************* Channel Authentication ****************************/ - -typedef struct { - SilcPurple sg; - SilcChannelEntry channel; - PurpleChat *c; - SilcDList pubkeys; -} *SilcPurpleChauth; - -static void -silcpurple_chat_chpk_add(void *user_data, const char *name) -{ - SilcPurpleChauth sgc = (SilcPurpleChauth)user_data; - SilcPurple sg = sgc->sg; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcPublicKey public_key; - SilcBuffer chpks, pk, chidp; - unsigned char mode[4]; - SilcUInt32 m; - - /* Load the public key */ - if (!silc_pkcs_load_public_key(name, &public_key)) { - silcpurple_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys); - silc_dlist_uninit(sgc->pubkeys); - silc_free(sgc); - purple_notify_error(client->application, - _("Add Channel Public Key"), - _("Could not load public key"), NULL, NULL); - return; - } - - pk = silc_public_key_payload_encode(public_key); - chpks = silc_buffer_alloc_size(2); - SILC_PUT16_MSB(1, chpks->head); - chpks = silc_argument_payload_encode_one(chpks, pk->data, - silc_buffer_len(pk), 0x00); - silc_buffer_free(pk); - - m = sgc->channel->mode; - m |= SILC_CHANNEL_MODE_CHANNEL_AUTH; - - /* Send CMODE */ - SILC_PUT32_MSB(m, mode); - chidp = silc_id_payload_encode(&sgc->channel->id, SILC_ID_CHANNEL); - silc_client_command_send(client, conn, SILC_COMMAND_CMODE, - silcpurple_command_reply, NULL, 3, - 1, chidp->data, silc_buffer_len(chidp), - 2, mode, sizeof(mode), - 9, chpks->data, silc_buffer_len(chpks)); - silc_buffer_free(chpks); - silc_buffer_free(chidp); - if (sgc->pubkeys) { - silc_dlist_start(sgc->pubkeys); - while ((public_key = silc_dlist_get(sgc->pubkeys))) - silc_pkcs_public_key_free(public_key); - silc_dlist_uninit(sgc->pubkeys); - } - silc_free(sgc); -} - -static void -silcpurple_chat_chpk_cancel(void *user_data, const char *name) -{ - SilcPurpleChauth sgc = (SilcPurpleChauth)user_data; - SilcPublicKey public_key; - - silcpurple_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys); - - if (sgc->pubkeys) { - silc_dlist_start(sgc->pubkeys); - while ((public_key = silc_dlist_get(sgc->pubkeys))) - silc_pkcs_public_key_free(public_key); - silc_dlist_uninit(sgc->pubkeys); - } - silc_free(sgc); -} - -static void -silcpurple_chat_chpk_cb(SilcPurpleChauth sgc, PurpleRequestFields *fields) -{ - SilcPurple sg = sgc->sg; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - PurpleRequestField *f; - GList *list; - SilcPublicKey public_key; - SilcBuffer chpks, pk, chidp; - SilcUInt16 c = 0, ct; - unsigned char mode[4]; - SilcUInt32 m; - - f = purple_request_fields_get_field(fields, "list"); - if (!purple_request_field_list_get_selected(f)) { - /* Add new public key */ - purple_request_file(sg->gc, _("Open Public Key..."), NULL, FALSE, - G_CALLBACK(silcpurple_chat_chpk_add), - G_CALLBACK(silcpurple_chat_chpk_cancel), - purple_request_cpar_from_connection(sg->gc), sgc); - return; - } - - list = purple_request_field_list_get_items(f); - chpks = silc_buffer_alloc_size(2); - - for (ct = 0; list; list = list->next, ct++) { - PurpleKeyValuePair *item = list->data; - - public_key = purple_request_field_list_get_data(f, item->key); - if (purple_request_field_list_is_selected(f, item->key)) { - /* Delete this public key */ - pk = silc_public_key_payload_encode(public_key); - chpks = silc_argument_payload_encode_one(chpks, pk->data, - silc_buffer_len(pk), 0x01); - silc_buffer_free(pk); - c++; - } - } - if (!c) { - silc_buffer_free(chpks); - return; - } - SILC_PUT16_MSB(c, chpks->head); - - m = sgc->channel->mode; - if (ct == c) - m &= ~SILC_CHANNEL_MODE_CHANNEL_AUTH; - - /* Send CMODE */ - SILC_PUT32_MSB(m, mode); - chidp = silc_id_payload_encode(&sgc->channel->id, SILC_ID_CHANNEL); - silc_client_command_send(client, conn, SILC_COMMAND_CMODE, - silcpurple_command_reply, NULL, 3, - 1, chidp->data, silc_buffer_len(chidp), - 2, mode, sizeof(mode), - 9, chpks->data, silc_buffer_len(chpks)); - silc_buffer_free(chpks); - silc_buffer_free(chidp); - if (sgc->pubkeys) { - silc_dlist_start(sgc->pubkeys); - while ((public_key = silc_dlist_get(sgc->pubkeys))) - silc_pkcs_public_key_free(public_key); - silc_dlist_uninit(sgc->pubkeys); - } - silc_free(sgc); -} - -static void -silcpurple_chat_chauth_ok(SilcPurpleChauth sgc, PurpleRequestFields *fields) -{ - SilcPurple sg = sgc->sg; - PurpleRequestField *f; - SilcPublicKey public_key; - const char *curpass, *val; - int set; - - f = purple_request_fields_get_field(fields, "passphrase"); - val = purple_request_field_string_get_value(f); - curpass = purple_blist_node_get_string((PurpleBlistNode *)sgc->c, "passphrase"); - - if (!val && curpass) - set = 0; - else if (val && !curpass) - set = 1; - else if (val && curpass && !purple_strequal(val, curpass)) - set = 1; - else - set = -1; - - if (set == 1) { - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - sgc->channel->channel_name, "+a", val, NULL); - purple_blist_node_set_string((PurpleBlistNode *)sgc->c, "passphrase", val); - } else if (set == 0) { - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - sgc->channel->channel_name, "-a", NULL); - purple_blist_node_remove_setting((PurpleBlistNode *)sgc->c, "passphrase"); - } - - if (sgc->pubkeys) { - silc_dlist_start(sgc->pubkeys); - while ((public_key = silc_dlist_get(sgc->pubkeys))) - silc_pkcs_public_key_free(public_key); - silc_dlist_uninit(sgc->pubkeys); - } - silc_free(sgc); -} - -void silcpurple_chat_chauth_show(SilcPurple sg, SilcChannelEntry channel, - SilcDList channel_pubkeys) -{ - SilcPublicKey public_key; - SilcSILCPublicKey silc_pubkey; - unsigned char *pk; - SilcUInt32 pk_len; - char *fingerprint, *babbleprint; - SilcPublicKeyIdentifier ident; - char tmp2[1024]; - const gchar *t; - PurpleRequestFields *fields; - PurpleRequestFieldGroup *g; - PurpleRequestField *f; - SilcPurpleChauth sgc; - const char *curpass = NULL; - - sgc = silc_calloc(1, sizeof(*sgc)); - if (!sgc) - return; - sgc->sg = sg; - sgc->channel = channel; - - fields = purple_request_fields_new(); - - if (sgc->c) - curpass = purple_blist_node_get_string((PurpleBlistNode *)sgc->c, "passphrase"); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_string_new("passphrase", _("Channel Passphrase"), - curpass, FALSE); - purple_request_field_string_set_masked(f, TRUE); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_label_new("l1", _("Channel Public Keys List")); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - t = _("Channel authentication is used to secure the channel from " - "unauthorized access. The authentication may be based on " - "passphrase and digital signatures. If passphrase is set, it " - "is required to be able to join. If channel public keys are set " - "then only users whose public keys are listed are able to join."); - - if (!channel_pubkeys || !silc_dlist_count(channel_pubkeys)) { - f = purple_request_field_list_new("list", NULL); - purple_request_field_group_add_field(g, f); - purple_request_fields(sg->gc, _("Channel Authentication"), - _("Channel Authentication"), t, fields, - _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb), - _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok), - purple_request_cpar_from_connection(sg->gc), sgc); - if (channel_pubkeys) - silc_dlist_uninit(channel_pubkeys); - return; - } - sgc->pubkeys = channel_pubkeys; - - g = purple_request_field_group_new(NULL); - f = purple_request_field_list_new("list", NULL); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - silc_dlist_start(channel_pubkeys); - while ((public_key = silc_dlist_get(channel_pubkeys))) { - pk = silc_pkcs_public_key_encode(public_key, &pk_len); - if (!pk) - continue; - fingerprint = silc_hash_fingerprint(NULL, pk + 4, pk_len - 4); - babbleprint = silc_hash_babbleprint(NULL, pk + 4, pk_len - 4); - - silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key); - ident = &silc_pubkey->identifier; - - g_snprintf(tmp2, sizeof(tmp2), "%s\n %s\n %s", - ident->realname ? ident->realname : ident->username ? - ident->username : "", fingerprint, babbleprint); - purple_request_field_list_add_icon(f, tmp2, NULL, public_key); - - silc_free(fingerprint); - silc_free(babbleprint); - } - - purple_request_field_list_set_multi_select(f, FALSE); - purple_request_fields(sg->gc, _("Channel Authentication"), - _("Channel Authentication"), t, fields, - _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb), - _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok), - purple_request_cpar_from_connection(sg->gc), sgc); -} - -static void -silcpurple_chat_chauth(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(purple_chat_get_account(chat)); - sg = purple_connection_get_protocol_data(gc); - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(purple_chat_get_components(chat), "channel"), - "+C", NULL); -} - - -/************************** Channel Private Groups **************************/ - -/* Private groups are "virtual" channels. They are groups inside a channel. - This is implemented by using channel private keys. By knowing a channel - private key user becomes part of that group and is able to talk on that - group. Other users, on the same channel, won't be able to see the - messages of that group. It is possible to have multiple groups inside - a channel - and thus having multiple private keys on the channel. */ - -typedef struct { - SilcPurple sg; - PurpleChat *c; - const char *channel; -} *SilcPurpleCharPrv; - -static void -silcpurple_chat_prv_add(SilcPurpleCharPrv p, PurpleRequestFields *fields) -{ - SilcPurple sg = p->sg; - gchar *tmp; - PurpleRequestField *f; - const char *name, *passphrase, *alias; - GHashTable *comp; - PurpleGroup *g; - PurpleChat *cn; - - f = purple_request_fields_get_field(fields, "name"); - name = purple_request_field_string_get_value(f); - if (!name) { - silc_free(p); - return; - } - f = purple_request_fields_get_field(fields, "passphrase"); - passphrase = purple_request_field_string_get_value(f); - f = purple_request_fields_get_field(fields, "alias"); - alias = purple_request_field_string_get_value(f); - - /* Add private group to buddy list */ - tmp = g_strdup_printf("%s [Private Group]", name); - comp = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); - g_hash_table_replace(comp, "channel", tmp); - g_hash_table_replace(comp, "passphrase", g_strdup(passphrase)); - - cn = purple_chat_new(sg->account, alias, comp); - g = purple_chat_get_group(p->c); - purple_blist_add_chat(cn, g, (PurpleBlistNode *)p->c); - - /* Associate to a real channel */ - purple_blist_node_set_string((PurpleBlistNode *)cn, "parentch", p->channel); - - /* Join the group */ - silcpurple_chat_join(NULL, sg->gc, comp); - - silc_free(p); -} - -static void -silcpurple_chat_prv_cancel(SilcPurpleCharPrv p, PurpleRequestFields *fields) -{ - silc_free(p); -} - -static void -silcpurple_chat_prv(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - SilcPurpleCharPrv p; - PurpleRequestFields *fields; - PurpleRequestFieldGroup *g; - PurpleRequestField *f; - char tmp[512]; - - g_return_if_fail(PURPLE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(purple_chat_get_account(chat)); - sg = purple_connection_get_protocol_data(gc); - - p = silc_calloc(1, sizeof(*p)); - if (!p) - return; - p->sg = sg; - - p->channel = g_hash_table_lookup(purple_chat_get_components(chat), "channel"); - p->c = purple_blist_find_chat(sg->account, p->channel); - - fields = purple_request_fields_new(); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_string_new("name", _("Group Name"), - NULL, FALSE); - purple_request_field_group_add_field(g, f); - - f = purple_request_field_string_new("passphrase", _("Passphrase"), - NULL, FALSE); - purple_request_field_string_set_masked(f, TRUE); - purple_request_field_group_add_field(g, f); - - f = purple_request_field_string_new("alias", _("Alias"), - NULL, FALSE); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - g_snprintf(tmp, sizeof(tmp), - _("Please enter the %s channel private group name and passphrase."), - p->channel); - purple_request_fields(gc, _("Add Channel Private Group"), NULL, tmp, fields, - _("Add"), G_CALLBACK(silcpurple_chat_prv_add), - _("Cancel"), G_CALLBACK(silcpurple_chat_prv_cancel), - purple_request_cpar_from_connection(gc), p); -} - - -/****************************** Channel Modes ********************************/ - -static void -silcpurple_chat_permanent_reset(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(purple_chat_get_account(chat)); - sg = purple_connection_get_protocol_data(gc); - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(purple_chat_get_components(chat), "channel"), - "-f", NULL); -} - -static void -silcpurple_chat_permanent(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - const char *channel; - - g_return_if_fail(PURPLE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(purple_chat_get_account(chat)); - sg = purple_connection_get_protocol_data(gc); - - if (!sg->conn) - return; - - /* XXX we should have ability to define which founder - key to use. Now we use the user's own public key - (default key). */ - - /* Call CMODE */ - channel = g_hash_table_lookup(purple_chat_get_components(chat), "channel"); - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", channel, - "+f", NULL); -} - -static void -silcpurple_chat_ulimit_cb(PurpleKeyValuePair *s, const char *limit) -{ - SilcPurple sg = s->value; - SilcChannelEntry channel; - guint ulimit = 0; - - channel = silc_client_get_channel(sg->client, sg->conn, s->key); - if (!channel) - return; - if (limit) - ulimit = strtoul(limit, NULL, 10); - - if (!limit || !(*limit) || *limit == '0') { - if (!limit || ulimit != channel->user_limit) { - silc_client_command_call(sg->client, sg->conn, NULL, - "CMODE", s->key, "-l", NULL); - } - } else if (ulimit != channel->user_limit) { - /* Call CMODE */ - silc_client_command_call(sg->client, sg->conn, NULL, - "CMODE", s->key, "+l", limit, NULL); - } - - purple_key_value_pair_free(s); -} - -static void -silcpurple_chat_ulimit(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - PurpleKeyValuePair *s; - SilcChannelEntry channel; - char *ch; - char tmp[32]; - - g_return_if_fail(PURPLE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(purple_chat_get_account(chat)); - sg = purple_connection_get_protocol_data(gc); - - if (!sg->conn) - return; - - ch = g_hash_table_lookup(purple_chat_get_components(chat), "channel"); - channel = silc_client_get_channel(sg->client, sg->conn, ch); - if (!channel) - return; - - s = purple_key_value_pair_new(ch, sg); - g_snprintf(tmp, sizeof(tmp), "%d", (int)channel->user_limit); - purple_request_input(gc, _("User Limit"), NULL, - _("Set user limit on channel. Set to zero to reset user limit."), - tmp, FALSE, FALSE, NULL, - _("OK"), G_CALLBACK(silcpurple_chat_ulimit_cb), - _("Cancel"), G_CALLBACK(silcpurple_chat_ulimit_cb), - purple_request_cpar_from_connection(gc), s); -} - -static void -silcpurple_chat_resettopic(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(purple_chat_get_account(chat)); - sg = purple_connection_get_protocol_data(gc); - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(purple_chat_get_components(chat), "channel"), - "-t", NULL); -} - -static void -silcpurple_chat_settopic(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(purple_chat_get_account(chat)); - sg = purple_connection_get_protocol_data(gc); - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(purple_chat_get_components(chat), "channel"), - "+t", NULL); -} - -static void -silcpurple_chat_resetprivate(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(purple_chat_get_account(chat)); - sg = purple_connection_get_protocol_data(gc); - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(purple_chat_get_components(chat), "channel"), - "-p", NULL); -} - -static void -silcpurple_chat_setprivate(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(purple_chat_get_account(chat)); - sg = purple_connection_get_protocol_data(gc); - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(purple_chat_get_components(chat), "channel"), - "+p", NULL); -} - -static void -silcpurple_chat_resetsecret(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(purple_chat_get_account(chat)); - sg = purple_connection_get_protocol_data(gc); - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(purple_chat_get_components(chat), "channel"), - "-s", NULL); -} - -static void -silcpurple_chat_setsecret(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(purple_chat_get_account(chat)); - sg = purple_connection_get_protocol_data(gc); - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(purple_chat_get_components(chat), "channel"), - "+s", NULL); -} - -typedef struct { - SilcPurple sg; - SilcChannelEntry channel; -} *SilcPurpleChatWb; - -static void -silcpurple_chat_wb(PurpleBlistNode *node, gpointer data) -{ - SilcPurpleChatWb wb = data; - silcpurple_wb_init_ch(wb->sg, wb->channel); - silc_free(wb); -} - -GList *silcpurple_chat_menu(PurpleChat *chat) -{ - GHashTable *components = purple_chat_get_components(chat); - PurpleConnection *gc = purple_account_get_connection(purple_chat_get_account(chat)); - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcClientConnection conn = sg->conn; - const char *chname = NULL; - SilcChannelEntry channel = NULL; - SilcChannelUser chu = NULL; - SilcUInt32 mode = 0; - - GList *m = NULL; - PurpleActionMenu *act; - - if (components) - chname = g_hash_table_lookup(components, "channel"); - if (!chname) - return NULL; - channel = silc_client_get_channel(sg->client, sg->conn, - (char *)chname); - if (channel) { - chu = silc_client_on_channel(channel, conn->local_entry); - if (chu) - mode = chu->mode; - } - - if (strstr(chname, "[Private Group]")) - return NULL; - - act = purple_action_menu_new(_("Get Info"), - G_CALLBACK(silcpurple_chat_getinfo_menu), - NULL, NULL); - m = g_list_append(m, act); - - if (chu) { - act = purple_action_menu_new(_("Add Private Group"), - G_CALLBACK(silcpurple_chat_prv), - NULL, NULL); - m = g_list_append(m, act); - } - - if (chu && mode & SILC_CHANNEL_UMODE_CHANFO) { - act = purple_action_menu_new(_("Channel Authentication"), - G_CALLBACK(silcpurple_chat_chauth), - NULL, NULL); - m = g_list_append(m, act); - - if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) { - act = purple_action_menu_new(_("Reset Permanent"), - G_CALLBACK(silcpurple_chat_permanent_reset), - NULL, NULL); - m = g_list_append(m, act); - } else { - act = purple_action_menu_new(_("Set Permanent"), - G_CALLBACK(silcpurple_chat_permanent), - NULL, NULL); - m = g_list_append(m, act); - } - } - - if (chu && mode & SILC_CHANNEL_UMODE_CHANOP) { - act = purple_action_menu_new(_("Set User Limit"), - G_CALLBACK(silcpurple_chat_ulimit), - NULL, NULL); - m = g_list_append(m, act); - - if (channel->mode & SILC_CHANNEL_MODE_TOPIC) { - act = purple_action_menu_new(_("Reset Topic Restriction"), - G_CALLBACK(silcpurple_chat_resettopic), - NULL, NULL); - m = g_list_append(m, act); - } else { - act = purple_action_menu_new(_("Set Topic Restriction"), - G_CALLBACK(silcpurple_chat_settopic), - NULL, NULL); - m = g_list_append(m, act); - } - - if (channel->mode & SILC_CHANNEL_MODE_PRIVATE) { - act = purple_action_menu_new(_("Reset Private Channel"), - G_CALLBACK(silcpurple_chat_resetprivate), - NULL, NULL); - m = g_list_append(m, act); - } else { - act = purple_action_menu_new(_("Set Private Channel"), - G_CALLBACK(silcpurple_chat_setprivate), - NULL, NULL); - m = g_list_append(m, act); - } - - if (channel->mode & SILC_CHANNEL_MODE_SECRET) { - act = purple_action_menu_new(_("Reset Secret Channel"), - G_CALLBACK(silcpurple_chat_resetsecret), - NULL, NULL); - m = g_list_append(m, act); - } else { - act = purple_action_menu_new(_("Set Secret Channel"), - G_CALLBACK(silcpurple_chat_setsecret), - NULL, NULL); - m = g_list_append(m, act); - } - } - - if (chu && channel) { - SilcPurpleChatWb wb; - wb = silc_calloc(1, sizeof(*wb)); - wb->sg = sg; - wb->channel = channel; - act = purple_action_menu_new(_("Draw On Whiteboard"), - G_CALLBACK(silcpurple_chat_wb), - (void *)wb, NULL); - m = g_list_append(m, act); - } - - return m; -} - - -/******************************* Joining Etc. ********************************/ - -char *silcpurple_get_chat_name(PurpleProtocolChat *protocol_chat, GHashTable *data) -{ - return g_strdup(g_hash_table_lookup(data, "channel")); -} - -void silcpurple_chat_join(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, GHashTable *data) -{ - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - const char *channel, *passphrase, *parentch; - - if (!conn) - return; - - channel = g_hash_table_lookup(data, "channel"); - passphrase = g_hash_table_lookup(data, "passphrase"); - - /* Check if we are joining a private group. Handle it - purely locally as it's not a real channel */ - if (strstr(channel, "[Private Group]")) { - SilcChannelEntry channel_entry; - SilcChannelPrivateKey key; - PurpleChat *c; - SilcPurplePrvgrp grp; - - c = purple_blist_find_chat(sg->account, channel); - parentch = purple_blist_node_get_string((PurpleBlistNode *)c, "parentch"); - if (!parentch) - return; - - channel_entry = silc_client_get_channel(sg->client, sg->conn, - (char *)parentch); - if (!channel_entry || - !silc_client_on_channel(channel_entry, sg->conn->local_entry)) { - char tmp[512]; - g_snprintf(tmp, sizeof(tmp), - _("You have to join the %s channel before you are " - "able to join the private group"), parentch); - purple_notify_error(gc, _("Join Private Group"), - _("Cannot join private group"), tmp, - purple_request_cpar_from_connection(gc)); - return; - } - - /* Add channel private key */ - if (!silc_client_add_channel_private_key(client, conn, - channel_entry, channel, - NULL, NULL, - (unsigned char *)passphrase, - strlen(passphrase), &key)) - return; - - /* Join the group */ - grp = silc_calloc(1, sizeof(*grp)); - if (!grp) - return; - grp->id = ++sg->channel_ids + SILCPURPLE_PRVGRP; - grp->chid = SILC_PTR_TO_32(channel_entry->context); - grp->parentch = parentch; - grp->channel = channel; - grp->key = key; - sg->grps = g_list_append(sg->grps, grp); - purple_serv_got_joined_chat(gc, grp->id, channel); - return; - } - - /* XXX We should have other properties here as well: - 1. whether to try to authenticate to the channel - 1a. with default key, - 1b. with specific key. - 2. whether to try to authenticate to become founder. - 2a. with default key, - 2b. with specific key. - - Since now such variety is not possible in the join dialog - we always use -founder and -auth options, which try to - do both 1 and 2 with default keys. */ - - /* Call JOIN */ - if ((passphrase != NULL) && (*passphrase != '\0')) - silc_client_command_call(client, conn, NULL, "JOIN", - channel, passphrase, "-auth", "-founder", NULL); - else - silc_client_command_call(client, conn, NULL, "JOIN", - channel, "-auth", "-founder", NULL); -} - -void silcpurple_chat_invite(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int id, const char *msg, - const char *name) -{ - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcHashTableList htl; - SilcChannelUser chu; - gboolean found = FALSE; - - if (!conn) - return; - - /* See if we are inviting on a private group. Invite - to the actual channel */ - if (id > SILCPURPLE_PRVGRP) { - GList *l; - SilcPurplePrvgrp prv; - - for (l = sg->grps; l; l = l->next) - if (((SilcPurplePrvgrp)l->data)->id == (gulong)id) - break; - if (!l) - return; - prv = l->data; - id = prv->chid; - } - - /* Find channel by id */ - silc_hash_table_list(conn->local_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - if (SILC_PTR_TO_32(chu->channel->context) == (gulong)id ) { - found = TRUE; - break; - } - } - silc_hash_table_list_reset(&htl); - if (!found) - return; - - /* Call INVITE */ - silc_client_command_call(client, conn, NULL, "INVITE", - chu->channel->channel_name, - name, NULL); -} - -void silcpurple_chat_leave(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int id) -{ - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcHashTableList htl; - SilcChannelUser chu; - gboolean found = FALSE; - GList *l; - SilcPurplePrvgrp prv; - - if (!conn) - return; - - /* See if we are leaving a private group */ - if (id > SILCPURPLE_PRVGRP) { - SilcChannelEntry channel; - - for (l = sg->grps; l; l = l->next) - if (((SilcPurplePrvgrp)l->data)->id == (gulong)id) - break; - if (!l) - return; - prv = l->data; - channel = silc_client_get_channel(sg->client, sg->conn, - (char *)prv->parentch); - if (!channel) - return; - silc_client_del_channel_private_key(client, conn, - channel, prv->key); - silc_free(prv); - sg->grps = g_list_delete_link(sg->grps, l); - purple_serv_got_chat_left(gc, id); - return; - } - - /* Find channel by id */ - silc_hash_table_list(conn->local_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - if (SILC_PTR_TO_32(chu->channel->context) == (gulong)id ) { - found = TRUE; - break; - } - } - silc_hash_table_list_reset(&htl); - if (!found) - return; - - /* Call LEAVE */ - silc_client_command_call(client, conn, NULL, "LEAVE", - chu->channel->channel_name, NULL); - - purple_serv_got_chat_left(gc, id); - - /* Leave from private groups on this channel as well */ - for (l = sg->grps; l; l = l->next) - if (((SilcPurplePrvgrp)l->data)->chid == (gulong)id) { - prv = l->data; - silc_client_del_channel_private_key(client, conn, - chu->channel, - prv->key); - purple_serv_got_chat_left(gc, prv->id); - silc_free(prv); - sg->grps = g_list_delete_link(sg->grps, l); - if (!sg->grps) - break; - } -} - -int silcpurple_chat_send(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int id, PurpleMessage *pmsg) -{ - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcHashTableList htl; - SilcChannelUser chu; - SilcChannelEntry channel = NULL; - SilcChannelPrivateKey key = NULL; - SilcMessageFlags flags; - int ret = 0; - const gchar *msg = purple_message_get_contents(pmsg); - char *msg2, *tmp; - gboolean found = FALSE; - gboolean sign = purple_account_get_bool(sg->account, "sign-verify", FALSE); - SilcDList list; - PurpleMessageFlags msgflags = purple_message_get_flags(pmsg); - - if (!msg || !conn) - return 0; - - flags = SILC_MESSAGE_FLAG_UTF8; - - tmp = msg2 = purple_unescape_html(msg); - - if (!g_ascii_strncasecmp(msg2, "/me ", 4)) - { - msg2 += 4; - if (!*msg2) { - g_free(tmp); - return 0; - } - flags |= SILC_MESSAGE_FLAG_ACTION; - } else if (strlen(msg) > 1 && msg[0] == '/') { - if (!silc_client_command_call(client, conn, msg + 1)) { - purple_notify_error(gc, _("Call Command"), - _("Cannot call command"), _("Unknown command"), - purple_request_cpar_from_connection(gc)); - } - g_free(tmp); - return 0; - } - - - if (sign) - flags |= SILC_MESSAGE_FLAG_SIGNED; - - /* Get the channel private key if we are sending on - private group */ - if (id > SILCPURPLE_PRVGRP) { - GList *l; - SilcPurplePrvgrp prv; - - for (l = sg->grps; l; l = l->next) - if (((SilcPurplePrvgrp)l->data)->id == (gulong)id) - break; - if (!l) { - g_free(tmp); - return 0; - } - prv = l->data; - channel = silc_client_get_channel(sg->client, sg->conn, - (char *)prv->parentch); - if (!channel) { - g_free(tmp); - return 0; - } - key = prv->key; - } - - if (!channel) { - /* Find channel by id */ - silc_hash_table_list(conn->local_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - if (SILC_PTR_TO_32(chu->channel->context) == (gulong)id ) { - found = TRUE; - break; - } - } - silc_hash_table_list_reset(&htl); - if (!found) { - g_free(tmp); - return 0; - } - channel = chu->channel; - } - - /* Check for images */ - if (msgflags & PURPLE_MESSAGE_IMAGES) { - list = silcpurple_image_message(msg, &flags); - if (list) { - /* Send one or more MIME message. If more than one, they - are MIME fragments due to over large message */ - SilcBuffer buf; - - silc_dlist_start(list); - while ((buf = silc_dlist_get(list)) != SILC_LIST_END) - ret = - silc_client_send_channel_message(client, conn, - channel, key, - flags, sg->sha1hash, - buf->data, - silc_buffer_len(buf)); - silc_mime_partial_free(list); - g_free(tmp); - - if (ret) - purple_serv_got_chat_in(gc, id, purple_connection_get_display_name(gc), msgflags, msg, time(NULL)); - return ret; - } - } - - /* Send channel message */ - ret = silc_client_send_channel_message(client, conn, channel, key, - flags, sg->sha1hash, - (unsigned char *)msg2, - strlen(msg2)); - if (ret) { - purple_serv_got_chat_in(gc, id, purple_connection_get_display_name(gc), msgflags, msg, - time(NULL)); - } - g_free(tmp); - - return ret; -} - -void silcpurple_chat_set_topic(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int id, const char *topic) -{ - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcHashTableList htl; - SilcChannelUser chu; - gboolean found = FALSE; - - if (!conn) - return; - - /* See if setting topic on private group. Set it - on the actual channel */ - if (id > SILCPURPLE_PRVGRP) { - GList *l; - SilcPurplePrvgrp prv; - - for (l = sg->grps; l; l = l->next) - if (((SilcPurplePrvgrp)l->data)->id == (gulong)id) - break; - if (!l) - return; - prv = l->data; - id = prv->chid; - } - - /* Find channel by id */ - silc_hash_table_list(conn->local_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - if (SILC_PTR_TO_32(chu->channel->context) == (gulong)id ) { - found = TRUE; - break; - } - } - silc_hash_table_list_reset(&htl); - if (!found) - return; - - /* Call TOPIC */ - silc_client_command_call(client, conn, NULL, "TOPIC", - chu->channel->channel_name, topic, NULL); -} - -PurpleRoomlist * -silcpurple_roomlist_get_list(PurpleProtocolRoomlist *protocol_roomlist, - PurpleConnection *gc) -{ - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - - if (!conn) - return NULL; - - if (sg->roomlist) - g_object_unref(sg->roomlist); - - sg->roomlist_cancelled = FALSE; - - sg->roomlist = purple_roomlist_new(purple_connection_get_account(gc)); - - /* Call LIST */ - silc_client_command_call(client, conn, "LIST"); - - purple_roomlist_set_in_progress(sg->roomlist, TRUE); - - return sg->roomlist; -} - -void -silcpurple_roomlist_cancel(PurpleProtocolRoomlist *protocol_roomlist, - PurpleRoomlist *list) -{ - PurpleAccount *account = purple_roomlist_get_account(list); - PurpleConnection *gc = purple_account_get_connection(account); - SilcPurple sg; - - if (!gc) - return; - sg = purple_connection_get_protocol_data(gc); - - purple_roomlist_set_in_progress(list, FALSE); - if (sg->roomlist == list) { - g_object_unref(sg->roomlist); - sg->roomlist = NULL; - sg->roomlist_cancelled = TRUE; - } -} diff --git a/libpurple/protocols/silc/ft.c b/libpurple/protocols/silc/ft.c deleted file mode 100644 index b04d1716ce..0000000000 --- a/libpurple/protocols/silc/ft.c +++ /dev/null @@ -1,546 +0,0 @@ -/* - - silcpurple_ft.c - - Author: Pekka Riikonen <priikone@silcnet.org> - - Copyright (C) 2004 - 2007 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. - -*/ - -#include <glib/gi18n-lib.h> -#include <glib/gstdio.h> - -#include "silcpurple.h" -#include "ft.h" - -/****************************** File Transfer ********************************/ - -/* This implements the secure file transfer protocol (SFTP) using the SILC - SFTP library implementation. The API we use from the SILC Toolkit is the - SILC Client file transfer API, as it provides a simple file transfer we - need in this case. We could use the SILC SFTP API directly, but it would - be an overkill since we'd effectively re-implement the file transfer what - the SILC Client's file transfer API already provides. - - From Purple we do NOT use the FT API to do the transfer as it is very limiting. - In fact it does not suite to file transfers like SFTP at all. For example, - it assumes that read operations are synchronous what they are not in SFTP. - It also assumes that the file transfer socket is to be handled by the Purple - eventloop, and this naturally is something we don't want to do in case of - SILC Toolkit. The FT API suites well to purely stream based file transfers - like HTTP GET and similar. - - For this reason, we directly access the Purple GKT FT API and hack the FT - API to merely provide the user interface experience and all the magic - is done in the SILC Toolkit. Ie. we update the statistics information in - the FT API for user interface, and that's it. A bit dirty but until the - FT API gets better this is the way to go. Good thing that FT API allowed - us to do this. */ - -struct _SilcPurpleXfer { - PurpleXfer parent; - - SilcPurple sg; - SilcClientEntry client_entry; - SilcUInt32 session_id; - char *hostname; - SilcUInt16 port; - - SilcClientFileName completion; - void *completion_context; -}; - -G_DEFINE_DYNAMIC_TYPE(SilcPurpleXfer, silcpurple_xfer, PURPLE_TYPE_XFER); - -static void -silcpurple_ftp_monitor(SilcClient client, - SilcClientConnection conn, - SilcClientMonitorStatus status, - SilcClientFileError error, - SilcUInt64 offset, - SilcUInt64 filesize, - SilcClientEntry client_entry, - SilcUInt32 session_id, - const char *filepath, - void *context) -{ - PurpleXfer *xfer = context; - SilcPurpleXfer *spx = SILCPURPLE_XFER(xfer); - PurpleConnection *gc = spx->sg->gc; - char tmp[256]; - - if (status == SILC_CLIENT_FILE_MONITOR_CLOSED) { - /* All started sessions terminate here */ - g_object_unref(xfer); - return; - } - - if (status == SILC_CLIENT_FILE_MONITOR_DISCONNECT) { - purple_notify_error(gc, _("Secure File Transfer"), _("Error " - "during file transfer"), _("Remote disconnected"), - purple_request_cpar_from_connection(gc)); - purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_REMOTE); - silc_client_file_close(client, conn, session_id); - return; - } - - if (status == SILC_CLIENT_FILE_MONITOR_KEY_AGREEMENT) - return; - - if (status == SILC_CLIENT_FILE_MONITOR_ERROR) { - if (error == SILC_CLIENT_FILE_NO_SUCH_FILE) { - g_snprintf(tmp, sizeof(tmp), "No such file %s", - filepath ? filepath : "[N/A]"); - purple_notify_error(gc, _("Secure File Transfer"), - _("Error during file transfer"), tmp, - purple_request_cpar_from_connection(gc)); - } else if (error == SILC_CLIENT_FILE_PERMISSION_DENIED) { - purple_notify_error(gc, _("Secure File Transfer"), - _("Error during file transfer"), - _("Permission denied"), - purple_request_cpar_from_connection(gc)); - } else if (error == SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED) { - purple_notify_error(gc, _("Secure File Transfer"), - _("Error during file transfer"), - _("Key agreement failed"), - purple_request_cpar_from_connection(gc)); - } else if (error == SILC_CLIENT_FILE_TIMEOUT) { - purple_notify_error(gc, _("Secure File Transfer"), - _("Error during file transfer"), - _("Connection timed out"), - purple_request_cpar_from_connection(gc)); - } else if (error == SILC_CLIENT_FILE_CONNECT_FAILED) { - purple_notify_error(gc, _("Secure File Transfer"), - _("Error during file transfer"), - _("Creating connection failed"), - purple_request_cpar_from_connection(gc)); - } else if (error == SILC_CLIENT_FILE_UNKNOWN_SESSION) { - purple_notify_error(gc, _("Secure File Transfer"), - _("Error during file transfer"), - _("File transfer session does not exist"), - purple_request_cpar_from_connection(gc)); - } - purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_REMOTE); - silc_client_file_close(client, conn, session_id); - return; - } - - /* Update file transfer UI */ - if (!offset && filesize) { - purple_xfer_set_size(xfer, filesize); - } - if (offset && filesize) { - purple_xfer_set_bytes_sent(xfer, offset); - } - - if (status == SILC_CLIENT_FILE_MONITOR_SEND || - status == SILC_CLIENT_FILE_MONITOR_RECEIVE) { - if (offset == filesize) { - /* Download finished */ - purple_xfer_set_completed(xfer, TRUE); - silc_client_file_close(client, conn, session_id); - } - } -} - -static void -silcpurple_ftp_cancel(PurpleXfer *xfer) -{ - SilcPurpleXfer *spx = SILCPURPLE_XFER(xfer); - - if (!spx) { - return; - } - - purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_LOCAL); - silc_client_file_close(spx->sg->client, spx->sg->conn, spx->session_id); -} - -static void -silcpurple_ftp_ask_name_ok(PurpleXfer *xfer) -{ - SilcPurpleXfer *spx = SILCPURPLE_XFER(xfer); - const char *name; - - if (!spx) { - return; - } - - name = purple_xfer_get_local_filename(xfer); - g_unlink(name); - spx->completion(name, spx->completion_context); -} - -static void -silcpurple_ftp_ask_name(SilcClient client, - SilcClientConnection conn, - SilcUInt32 session_id, - const char *remote_filename, - SilcClientFileName completion, - void *completion_context, - void *context) -{ - PurpleXfer *xfer = context; - SilcPurpleXfer *spx = SILCPURPLE_XFER(xfer); - - spx->completion = completion; - spx->completion_context = completion_context; - - /* Request to save the file */ - purple_xfer_set_filename(xfer, remote_filename); - purple_xfer_request(xfer); -} - -static void -silcpurple_ftp_request_result(PurpleXfer *xfer) -{ - SilcPurpleXfer *spx = SILCPURPLE_XFER(xfer); - SilcClientFileError status; - PurpleConnection *gc = spx->sg->gc; - SilcClientConnectionParams params; - gboolean local = spx->hostname ? FALSE : TRUE; - char *local_ip = NULL, *remote_ip = NULL; - SilcSocket sock; - - if (purple_xfer_get_status(xfer) != PURPLE_XFER_STATUS_ACCEPTED) { - return; - } - - silc_socket_stream_get_info(silc_packet_stream_get_stream(spx->sg->conn->stream), - &sock, NULL, NULL, NULL); - - if (local) { - /* Do the same magic what we do with key agreement (see silcpurple_buddy.c) - to see if we are behind NAT. */ - if (silc_net_check_local_by_sock(sock, NULL, &local_ip)) { - /* Check if the IP is private */ - if (silcpurple_ip_is_private(local_ip)) { - local = TRUE; - /* Local IP is private, resolve the remote server IP to see whether - we are talking to Internet or just on LAN. */ - if (silc_net_check_host_by_sock(sock, NULL, - &remote_ip)) - if (silcpurple_ip_is_private(remote_ip)) - /* We assume we are in LAN. Let's provide the connection point. */ - local = TRUE; - } - } - - if (local && !local_ip) - local_ip = silc_net_localip(); - } - - memset(¶ms, 0, sizeof(params)); - params.timeout_secs = 60; - if (local) - /* Provide connection point */ - params.local_ip = local_ip; - - /* Start the file transfer */ - status = silc_client_file_receive(spx->sg->client, spx->sg->conn, - ¶ms, spx->sg->public_key, - spx->sg->private_key, - silcpurple_ftp_monitor, xfer, - NULL, spx->session_id, - silcpurple_ftp_ask_name, xfer); - switch (status) { - case SILC_CLIENT_FILE_OK: - silc_free(local_ip); - silc_free(remote_ip); - return; - break; - - case SILC_CLIENT_FILE_UNKNOWN_SESSION: - purple_notify_error(gc, _("Secure File Transfer"), - _("No file transfer session active"), NULL, - purple_request_cpar_from_connection(gc)); - break; - - case SILC_CLIENT_FILE_ALREADY_STARTED: - purple_notify_error(gc, _("Secure File Transfer"), - _("File transfer already started"), NULL, - purple_request_cpar_from_connection(gc)); - break; - - case SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED: - purple_notify_error(gc, _("Secure File Transfer"), - _("Could not perform key agreement for file transfer"), - NULL, purple_request_cpar_from_connection(gc)); - break; - - default: - purple_notify_error(gc, _("Secure File Transfer"), - _("Could not start the file transfer"), NULL, - purple_request_cpar_from_connection(gc)); - break; - } - - /* Error */ - g_object_unref(xfer); - silc_free(local_ip); - silc_free(remote_ip); -} - -static void -silcpurple_ftp_request_init(PurpleXfer *xfer) -{ - SilcPurpleXfer *spx = SILCPURPLE_XFER(xfer); - - if (spx->completion) { - silcpurple_ftp_ask_name_ok(xfer); - } else { - silcpurple_ftp_request_result(xfer); - } -} - -static void -silcpurple_ftp_request_denied(PurpleXfer *xfer) -{ - SilcPurpleXfer *spx = SILCPURPLE_XFER(xfer); - - if (!spx) { - return; - } - - /* Cancel the transmission */ - if (spx->completion) { - spx->completion(NULL, spx->completion_context); - } - silc_client_file_close(spx->sg->client, spx->sg->conn, spx->session_id); -} - -void silcpurple_ftp_request(SilcClient client, SilcClientConnection conn, - SilcClientEntry client_entry, SilcUInt32 session_id, - const char *hostname, SilcUInt16 port) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcPurpleXfer *spx; - - spx = g_object_new(SILCPURPLE_TYPE_XFER, - "account", sg->account, - "type", PURPLE_XFER_TYPE_RECEIVE, - "remote-user", client_entry->nickname, - NULL); - - spx->sg = sg; - spx->client_entry = client_entry; - spx->session_id = session_id; - spx->hostname = g_strdup(hostname); - spx->port = port; - - purple_xfer_start(PURPLE_XFER(spx), -1, hostname, port); - - /* File transfer request */ - purple_xfer_request(PURPLE_XFER(spx)); -} - -static void -silcpurple_ftp_send_cancel(PurpleXfer *xfer) -{ - SilcPurpleXfer *spx = SILCPURPLE_XFER(xfer); - - if (!spx) { - return; - } - - /* This call will free all resources */ - silc_client_file_close(spx->sg->client, spx->sg->conn, spx->session_id); -} - -static void -silcpurple_ftp_send(PurpleXfer *xfer) -{ - SilcPurpleXfer *spx = SILCPURPLE_XFER(xfer); - const char *name; - char *local_ip = NULL, *remote_ip = NULL; - gboolean local = TRUE; - SilcClientConnectionParams params; - SilcSocket sock; - - if (!spx) { - return; - } - - name = purple_xfer_get_local_filename(xfer); - - silc_socket_stream_get_info(silc_packet_stream_get_stream(spx->sg->conn->stream), - &sock, NULL, NULL, NULL); - - /* Do the same magic what we do with key agreement (see silcpurple_buddy.c) - to see if we are behind NAT. */ - if (silc_net_check_local_by_sock(sock, NULL, &local_ip)) { - /* Check if the IP is private */ - if (silcpurple_ip_is_private(local_ip)) { - local = FALSE; - /* Local IP is private, resolve the remote server IP to see whether - we are talking to Internet or just on LAN. */ - if (silc_net_check_host_by_sock(sock, NULL, - &remote_ip)) - if (silcpurple_ip_is_private(remote_ip)) - /* We assume we are in LAN. Let's provide the connection point. */ - local = TRUE; - } - } - - if (local && !local_ip) - local_ip = silc_net_localip(); - - memset(¶ms, 0, sizeof(params)); - params.timeout_secs = 60; - if (local) - /* Provide connection point */ - params.local_ip = local_ip; - - /* Send the file */ - silc_client_file_send(spx->sg->client, spx->sg->conn, - spx->client_entry, ¶ms, - spx->sg->public_key, spx->sg->private_key, - silcpurple_ftp_monitor, xfer, - name, &spx->session_id); - - silc_free(local_ip); - silc_free(remote_ip); -} - -static void -silcpurple_ftp_send_file_resolved(SilcClient client, - SilcClientConnection conn, - SilcStatus status, - SilcDList clients, - void *context) -{ - PurpleConnection *gc = client->application; - char tmp[256]; - - if (!clients) { - g_snprintf(tmp, sizeof(tmp), - _("User %s is not present in the network"), - (const char *)context); - purple_notify_error(gc, _("Secure File Transfer"), - _("Cannot send file"), tmp, - purple_request_cpar_from_connection(gc)); - g_free(context); - return; - } - - silcpurple_ftp_send_file(NULL, client->application, (const char *)context, NULL); - g_free(context); -} - -PurpleXfer *silcpurple_ftp_new_xfer(PurpleProtocolXfer *prplxfer, PurpleConnection *gc, const char *name) -{ - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcDList clients; - SilcClientEntry client_entry; - SilcPurpleXfer *spx; - - g_return_val_if_fail(name != NULL, NULL); - - /* Find client entry */ - clients = silc_client_get_clients_local(client, conn, name, FALSE); - if (!clients) { - silc_client_get_clients(client, conn, name, NULL, - silcpurple_ftp_send_file_resolved, - g_strdup(name)); - return NULL; - } - silc_dlist_start(clients); - - client_entry = silc_dlist_get(clients); - silc_free(clients); - - spx = g_object_new(SILCPURPLE_TYPE_XFER, - "account", sg->account, - "type", PURPLE_XFER_TYPE_SEND, - "remote-user", client_entry->nickname, - NULL); - - spx->sg = sg; - spx->client_entry = client_entry; - - return PURPLE_XFER(spx); -} - -void silcpurple_ftp_send_file(PurpleProtocolXfer *prplxfer, PurpleConnection *gc, const char *name, const char *file) -{ - PurpleXfer *xfer = silcpurple_ftp_new_xfer(prplxfer, gc, name); - - g_return_if_fail(xfer != NULL); - - /* Choose file to send */ - if (file) - purple_xfer_request_accepted(xfer, file); - else - purple_xfer_request(xfer); -} - -static void -silcpurple_ftp_init(PurpleXfer *xfer) -{ - switch(purple_xfer_get_xfer_type(xfer)) { - case PURPLE_XFER_TYPE_SEND: - silcpurple_ftp_send(xfer); - break; - case PURPLE_XFER_TYPE_RECEIVE: - silcpurple_ftp_request_init(xfer); - break; - case PURPLE_XFER_TYPE_UNKNOWN: - g_return_if_reached(); - break; - } -} - -/****************************************************************************** - * GObject Implementation - *****************************************************************************/ -static void -silcpurple_xfer_init(SilcPurpleXfer *spx) -{ -} - -static void -silcpurple_xfer_finalize(GObject *obj) { - SilcPurpleXfer *spx = SILCPURPLE_XFER(obj); - - g_free(spx->hostname); - - G_OBJECT_CLASS(silcpurple_xfer_parent_class)->finalize(obj); -} - -static void -silcpurple_xfer_class_init(SilcPurpleXferClass *klass) { - GObjectClass *obj_class = G_OBJECT_CLASS(klass); - PurpleXferClass *xfer_class = PURPLE_XFER_CLASS(klass); - - obj_class->finalize = silcpurple_xfer_finalize; - - xfer_class->init = silcpurple_ftp_init; - xfer_class->request_denied = silcpurple_ftp_request_denied; - xfer_class->cancel_send = silcpurple_ftp_send_cancel; - xfer_class->cancel_recv = silcpurple_ftp_cancel; -} - -static void -silcpurple_xfer_class_finalize(SilcPurpleXferClass *klass) { -} - -/****************************************************************************** - * Public API - *****************************************************************************/ -void -silcpurple_xfer_register(GTypeModule *module) { - silcpurple_xfer_register_type(module); -} diff --git a/libpurple/protocols/silc/ft.h b/libpurple/protocols/silc/ft.h deleted file mode 100644 index 7ab7105b43..0000000000 --- a/libpurple/protocols/silc/ft.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Purple - Internet Messaging Library - * Copyright (C) Pidgin Developers <devel@pidgin.im> - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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. - * - * 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, see <https://www.gnu.org/licenses/>. - */ - -#ifndef PURPLE_SILC_FT_H -#define PURPLE_SILC_FT_H - -#include <purple.h> - -G_BEGIN_DECLS - -#define SILCPURPLE_TYPE_XFER (silcpurple_xfer_get_type()) -G_DECLARE_FINAL_TYPE(SilcPurpleXfer, silcpurple_xfer, SILCPURPLE, XFER, PurpleXfer); - -void silcpurple_xfer_register(GTypeModule *module); - -G_END_DECLS - -#endif /* PURPLE_SILC_FT_H */ diff --git a/libpurple/protocols/silc/meson.build b/libpurple/protocols/silc/meson.build deleted file mode 100644 index 9d58df5895..0000000000 --- a/libpurple/protocols/silc/meson.build +++ /dev/null @@ -1,28 +0,0 @@ -SILC_SOURCES = [ - 'buddy.c', - 'chat.c', - 'ft.c', - 'ft.h', - 'ops.c', - 'pk.c', - 'silc.c', - 'silcpurple.h', - 'util.c', - 'wb.c', - 'wb.h' -] - -if DYNAMIC_SILC - silc_resources = gnome.compile_resources('silcresource', - 'resources/silc.gresource.xml', - source_dir : 'resources', - c_name : 'silc') - SILC_SOURCES += silc_resources - - silc_prpl = shared_library('silcpurple', SILC_SOURCES, - c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="Purple-SILC"'], - dependencies : [silc, libpurple_dep, glib], - install : true, install_dir : PURPLE_PLUGINDIR) - - devenv.append('PURPLE_PLUGIN_PATH', meson.current_build_dir()) -endif diff --git a/libpurple/protocols/silc/ops.c b/libpurple/protocols/silc/ops.c deleted file mode 100644 index 236b04f063..0000000000 --- a/libpurple/protocols/silc/ops.c +++ /dev/null @@ -1,1825 +0,0 @@ -/* - - silcpurple_ops.c - - Author: Pekka Riikonen <priikone@silcnet.org> - - Copyright (C) 2004 - 2007 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. - -*/ - -#include <glib/gi18n-lib.h> -#include <glib/gstdio.h> - -#include "libpurple/glibcompat.h" - -#include "silcpurple.h" -#include "wb.h" - -static void -silc_channel_message(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcChannelEntry channel, - SilcMessagePayload payload, - SilcChannelPrivateKey key, SilcMessageFlags flags, - const unsigned char *message, - SilcUInt32 message_len); -static void -silc_private_message(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcMessagePayload payload, - SilcMessageFlags flags, const unsigned char *message, - SilcUInt32 message_len); -static void -silc_ask_passphrase(SilcClient client, SilcClientConnection conn, - SilcAskPassphrase completion, void *context); - -/* Message sent to the application by library. `conn' associates the - message to a specific connection. `conn', however, may be NULL. - The `type' indicates the type of the message sent by the library. - The application can for example filter the message according the - type. */ - -void silc_say(SilcClient client, SilcClientConnection conn, - SilcClientMessageType type, char *msg, ...) -{ - char tmp[256]; - va_list va; - PurpleConnection *gc = NULL; - PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR; - - va_start(va, msg); - silc_vsnprintf(tmp, sizeof(tmp), msg, va); - va_end(va); - - if (type != SILC_CLIENT_MESSAGE_ERROR) { - purple_debug_misc("silc", "silc_say (%d) %s\n", type, tmp); - return; - } - - purple_debug_error("silc", "silc_say error: %s\n", tmp); - - if (purple_strequal(tmp, "Authentication failed")) - reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; - - if (client != NULL) - gc = client->application; - - if (gc != NULL) - purple_connection_error(gc, reason, tmp); - else - purple_notify_error(NULL, _("Error"), _("Error occurred"), tmp, NULL); -} - -/* Processes incoming MIME message. Can be private message or channel - message. Returns TRUE if the message `mime' was displayed. */ - -static SilcBool -silcpurple_mime_message(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcChannelEntry channel, - SilcMessagePayload payload, SilcChannelPrivateKey key, - SilcMessageFlags flags, SilcMime mime, - gboolean recursive) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = purple_connection_get_protocol_data(gc); - const char *type; - const unsigned char *data; - SilcUInt32 data_len; - PurpleMessageFlags cflags = 0; - PurpleConversation *chat = NULL; - PurpleConversationManager *manager = NULL; - SilcBool ret = FALSE; - - if (!mime) - return FALSE; - - /* Check for fragmented MIME message */ - if (silc_mime_is_partial(mime)) { - if (!sg->mimeass) - sg->mimeass = silc_mime_assembler_alloc(); - - /* Defragment */ - mime = silc_mime_assemble(sg->mimeass, mime); - if (!mime) - /* More fragments to come */ - return FALSE; - - /* Process the complete message */ - return silcpurple_mime_message(client, conn, sender, channel, - payload, key, flags, mime, - FALSE); - } - - /* Check for multipart message */ - if (silc_mime_is_multipart(mime)) { - SilcMime p; - const char *mtype; - SilcDList parts = silc_mime_get_multiparts(mime, &mtype); - - if (purple_strequal(mtype, "mixed")) { - /* Contains multiple messages */ - silc_dlist_start(parts); - while ((p = silc_dlist_get(parts)) != SILC_LIST_END) { - /* Recursively process parts */ - ret = silcpurple_mime_message(client, conn, sender, channel, - payload, key, flags, p, TRUE); - } - } - - if (purple_strequal(mtype, "alternative")) { - /* Same message in alternative formats. Kopete sends - these. Go in order from last to first. */ - silc_dlist_end(parts); - while ((p = silc_dlist_get(parts)) != SILC_LIST_END) { - /* Go through the alternatives and display the first - one we support. */ - if (silcpurple_mime_message(client, conn, sender, channel, - payload, key, flags, p, TRUE)) { - ret = TRUE; - break; - } - } - } - - goto out; - } - - /* Get content type and MIME data */ - type = silc_mime_get_field(mime, "Content-Type"); - if (!type) - goto out; - data = silc_mime_get_data(mime, &data_len); - if (!data) - goto out; - - /* Process according to content type */ - - /* Plain text */ - if (strstr(type, "text/plain")) { - /* Default is UTF-8, don't check for other charsets */ - if (!strstr(type, "utf-8")) - goto out; - - if (channel) - silc_channel_message(client, conn, sender, channel, - payload, key, - SILC_MESSAGE_FLAG_UTF8, data, - data_len); - else - silc_private_message(client, conn, sender, payload, - SILC_MESSAGE_FLAG_UTF8, data, - data_len); - ret = TRUE; - goto out; - } - - manager = purple_conversation_manager_get_default(); - - /* Image */ - if (g_str_has_prefix(type, "image/")) { - char tmp[32]; - PurpleImage *img; - guint img_id; - - /* Get channel chat (if message is for channel) */ - if (key && channel) { - GList *l; - SilcPurplePrvgrp prv; - - for (l = sg->grps; l; l = l->next) - if (((SilcPurplePrvgrp)l->data)->key == key) { - prv = l->data; - chat = purple_conversation_manager_find_chat(manager, - sg->account, - prv->channel); - break; - } - } - if (channel && !chat) { - chat = purple_conversation_manager_find_chat(manager, sg->account, - channel->channel_name); - } - - if (channel && !chat) { - goto out; - } - - img = purple_image_new_from_data(data, data_len); - if (!img) - goto out; - img_id = purple_image_store_add_temporary(img); - if (!img_id) { - g_clear_object(&img); - goto out; - } - - cflags |= PURPLE_MESSAGE_IMAGES | PURPLE_MESSAGE_RECV; - g_snprintf(tmp, sizeof(tmp), "<img src=\"" - PURPLE_IMAGE_STORE_PROTOCOL "%u\">", img_id); - - if (channel) { - purple_serv_got_chat_in(gc, - purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(chat)), - sender->nickname, cflags, tmp, time(NULL)); - } else { - purple_serv_got_im(gc, sender->nickname, - tmp, cflags, time(NULL)); - } - - g_clear_object(&img); - - goto out; - } - - /* Whiteboard message */ - if (strstr(type, "application/x-wb") && - !purple_account_get_bool(sg->account, "block-wb", FALSE)) { - if (channel) - silcpurple_wb_receive_ch(client, conn, sender, channel, - payload, flags, data, data_len); - else - silcpurple_wb_receive(client, conn, sender, payload, - flags, data, data_len); - ret = TRUE; - goto out; - } - - out: - if (!recursive) - silc_mime_free(mime); - return ret; -} - -/* Message for a channel. The `sender' is the sender of the message - The `channel' is the channel. The `message' is the message. Note - that `message' maybe NULL. The `flags' indicates message flags - and it is used to determine how the message can be interpreted - (like it may tell the message is multimedia message). */ - -static void -silc_channel_message(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcChannelEntry channel, - SilcMessagePayload payload, - SilcChannelPrivateKey key, SilcMessageFlags flags, - const unsigned char *message, - SilcUInt32 message_len) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = purple_connection_get_protocol_data(gc); - PurpleConversation *chat = NULL; - PurpleConversationManager *manager = NULL; - char *msg, *tmp; - - if (!message) - return; - - manager = purple_conversation_manager_get_default(); - - if (key) { - GList *l; - SilcPurplePrvgrp prv; - - for (l = sg->grps; l; l = l->next) - if (((SilcPurplePrvgrp)l->data)->key == key) { - prv = l->data; - chat = purple_conversation_manager_find_chat(manager, sg->account, - prv->channel); - break; - } - } - if (!chat) { - chat = purple_conversation_manager_find_chat(manager, sg->account, - channel->channel_name); - } - - if (!chat) { - return; - } - - if (flags & SILC_MESSAGE_FLAG_SIGNED && - purple_account_get_bool(sg->account, "sign-verify", FALSE)) { - /* XXX */ - } - - if (flags & SILC_MESSAGE_FLAG_DATA) { - /* Process MIME message */ - SilcMime mime; - mime = silc_mime_decode(NULL, message, message_len); - silcpurple_mime_message(client, conn, sender, channel, payload, - key, flags, mime, FALSE); - return; - } - - if (flags & SILC_MESSAGE_FLAG_ACTION) { - msg = g_strdup_printf("/me %s", - (const char *)message); - if (!msg) - return; - - tmp = g_markup_escape_text(msg, -1); - /* Send to Purple */ - purple_serv_got_chat_in(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(chat)), - sender->nickname, PURPLE_MESSAGE_RECV, tmp, time(NULL)); - g_free(tmp); - g_free(msg); - return; - } - - if (flags & SILC_MESSAGE_FLAG_NOTICE) { - msg = g_strdup_printf("(notice) <I>%s</I> %s", - sender->nickname, (const char *)message); - if (!msg) - return; - - /* Send to Purple */ - purple_conversation_write_system_message( - PURPLE_CONVERSATION(chat), msg, 0); - g_free(msg); - return; - } - - if (flags & SILC_MESSAGE_FLAG_UTF8) { - const char *msg = (const char *)message; - char *salvaged = NULL; - if (!g_utf8_validate((const char *)message, -1, NULL)) { - salvaged = g_utf8_make_valid((const char *)message, -1); - msg = salvaged; - } - tmp = g_markup_escape_text(msg, -1); - /* Send to Purple */ - purple_serv_got_chat_in(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(chat)), - sender->nickname, PURPLE_MESSAGE_RECV, tmp, time(NULL)); - g_free(salvaged); - g_free(tmp); - } -} - - -/* Private message to the client. The `sender' is the sender of the - message. The message is `message'and maybe NULL. The `flags' - indicates message flags and it is used to determine how the message - can be interpreted (like it may tell the message is multimedia - message). */ - -static void -silc_private_message(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcMessagePayload payload, - SilcMessageFlags flags, const unsigned char *message, - SilcUInt32 message_len) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = purple_connection_get_protocol_data(gc); - PurpleConversation *convo; - PurpleConversationManager *manager = NULL; - char *msg, *tmp; - - if (!message) { - return; - } - - manager = purple_conversation_manager_get_default(); - /* XXX - Should this be PURPLE_CONV_TYPE_IM? */ - convo = purple_conversation_manager_find(manager, sg->account, - sender->nickname); - - if (flags & SILC_MESSAGE_FLAG_SIGNED && - purple_account_get_bool(sg->account, "sign-verify", FALSE)) { - /* XXX */ - } - - if (flags & SILC_MESSAGE_FLAG_DATA) { - /* Process MIME message */ - SilcMime mime; - mime = silc_mime_decode(NULL, message, message_len); - silcpurple_mime_message(client, conn, sender, NULL, payload, - NULL, flags, mime, FALSE); - return; - } - - if (flags & SILC_MESSAGE_FLAG_ACTION && convo) { - msg = g_strdup_printf("/me %s", - (const char *)message); - if (!msg) - return; - - /* Send to Purple */ - tmp = g_markup_escape_text(msg, -1); - purple_serv_got_im(gc, sender->nickname, tmp, 0, time(NULL)); - g_free(msg); - g_free(tmp); - return; - } - - if (flags & SILC_MESSAGE_FLAG_NOTICE && convo) { - msg = g_strdup_printf("(notice) <I>%s</I> %s", - sender->nickname, (const char *)message); - if (!msg) - return; - - /* Send to Purple */ - purple_conversation_write_system_message(convo, msg, 0); - g_free(msg); - return; - } - - if (flags & SILC_MESSAGE_FLAG_UTF8) { - const char *msg = (const char *)message; - char *salvaged = NULL; - if (!g_utf8_validate((const char *)message, -1, NULL)) { - salvaged = g_utf8_make_valid((const char *)message, -1); - msg = salvaged; - } - tmp = g_markup_escape_text(msg, -1); - /* Send to Purple */ - purple_serv_got_im(gc, sender->nickname, tmp, 0, time(NULL)); - g_free(salvaged); - g_free(tmp); - } -} - - -/* Notify message to the client. The notify arguments are sent in the - same order as servers sends them. The arguments are same as received - from the server except for ID's. If ID is received application receives - the corresponding entry to the ID. For example, if Client ID is received - application receives SilcClientEntry. Also, if the notify type is - for channel the channel entry is sent to application (even if server - does not send it because client library gets the channel entry from - the Channel ID in the packet's header). */ - -static void -silc_notify(SilcClient client, SilcClientConnection conn, - SilcNotifyType type, ...) -{ - va_list va; - PurpleConnection *gc = client->application; - PurpleConversationManager *manager; - SilcPurple sg = purple_connection_get_protocol_data(gc); - PurpleAccount *account = purple_connection_get_account(gc); - PurpleConversation *chat; - SilcClientEntry client_entry, client_entry2; - SilcChannelEntry channel; - SilcServerEntry server_entry; - SilcIdType idtype; - void *entry; - SilcUInt32 mode; - SilcHashTableList htl; - SilcChannelUser chu; - char buf[512], buf2[512], *tmp, *name; - SilcNotifyType notify; - PurpleBuddy *b; - SilcDList list; - - va_start(va, type); - memset(buf, 0, sizeof(buf)); - - manager = purple_conversation_manager_get_default(); - - switch (type) { - - case SILC_NOTIFY_TYPE_NONE: - break; - - case SILC_NOTIFY_TYPE_INVITE: - { - GHashTable *components; - (void)va_arg(va, SilcChannelEntry); - name = va_arg(va, char *); - client_entry = va_arg(va, SilcClientEntry); - - components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); - g_hash_table_insert(components, g_strdup("channel"), g_strdup(name)); - purple_serv_got_chat_invite(gc, name, client_entry->nickname, NULL, components); - } - break; - - case SILC_NOTIFY_TYPE_JOIN: - client_entry = va_arg(va, SilcClientEntry); - channel = va_arg(va, SilcChannelEntry); - - /* If we joined channel, do nothing */ - if (client_entry == conn->local_entry) - break; - - chat = purple_conversation_manager_find_chat(manager, sg->account, - channel->channel_name); - if (!chat) { - break; - } - - /* Join user to channel */ - g_snprintf(buf, sizeof(buf), "%s@%s", - client_entry->username, client_entry->hostname); - purple_chat_conversation_add_user(PURPLE_CHAT_CONVERSATION(chat), - client_entry->nickname, buf, PURPLE_CHAT_USER_NONE, TRUE); - - break; - - case SILC_NOTIFY_TYPE_LEAVE: - client_entry = va_arg(va, SilcClientEntry); - channel = va_arg(va, SilcChannelEntry); - - chat = purple_conversation_manager_find_chat(manager, sg->account, - channel->channel_name); - if (!chat) { - break; - } - - /* Remove user from channel */ - purple_chat_conversation_remove_user(PURPLE_CHAT_CONVERSATION(chat), - client_entry->nickname, NULL); - - break; - - case SILC_NOTIFY_TYPE_SIGNOFF: - client_entry = va_arg(va, SilcClientEntry); - tmp = va_arg(va, char *); - - /* Remove from all channels */ - silc_hash_table_list(client_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - chat = purple_conversation_manager_find_chat(manager, sg->account, - chu->channel->channel_name); - if (!chat) { - continue; - } - purple_chat_conversation_remove_user(PURPLE_CHAT_CONVERSATION(chat), - client_entry->nickname, - tmp); - } - silc_hash_table_list_reset(&htl); - - break; - - case SILC_NOTIFY_TYPE_TOPIC_SET: - { - char *esc, *tmp2; - idtype = va_arg(va, int); - entry = va_arg(va, void *); - tmp = va_arg(va, char *); - channel = va_arg(va, SilcChannelEntry); - - chat = purple_conversation_manager_find_chat(manager, sg->account, - channel->channel_name); - if (!chat) { - break; - } - - if (!tmp) { - break; - } - - esc = g_markup_escape_text(tmp, -1); - tmp2 = purple_markup_linkify(esc); - g_free(esc); - - if (idtype == SILC_ID_CLIENT) { - client_entry = (SilcClientEntry)entry; - g_snprintf(buf, sizeof(buf), - _("%s has changed the topic of <I>%s</I> to: %s"), - client_entry->nickname, channel->channel_name, tmp2); - purple_conversation_write_system_message( - PURPLE_CONVERSATION(chat), buf, 0); - purple_chat_conversation_set_topic(PURPLE_CHAT_CONVERSATION(chat), - client_entry->nickname, tmp); - } else if (idtype == SILC_ID_SERVER) { - server_entry = (SilcServerEntry)entry; - g_snprintf(buf, sizeof(buf), - _("%s has changed the topic of <I>%s</I> to: %s"), - server_entry->server_name, channel->channel_name, tmp2); - purple_conversation_write_system_message( - PURPLE_CONVERSATION(chat), buf, 0); - purple_chat_conversation_set_topic(PURPLE_CHAT_CONVERSATION(chat), - server_entry->server_name, tmp); - } else if (idtype == SILC_ID_CHANNEL) { - channel = (SilcChannelEntry)entry; - g_snprintf(buf, sizeof(buf), - _("%s has changed the topic of <I>%s</I> to: %s"), - channel->channel_name, channel->channel_name, tmp2); - purple_conversation_write_system_message( - PURPLE_CONVERSATION(chat), buf, 0); - purple_chat_conversation_set_topic(PURPLE_CHAT_CONVERSATION(chat), - channel->channel_name, tmp); - } else { - purple_chat_conversation_set_topic(PURPLE_CHAT_CONVERSATION(chat), NULL, tmp); - } - - g_free(tmp2); - - break; - - } - case SILC_NOTIFY_TYPE_NICK_CHANGE: - client_entry = va_arg(va, SilcClientEntry); - tmp = va_arg(va, char *); /* Old nick */ - name = va_arg(va, char *); /* New nick */ - - if (purple_strequal(tmp, name)) - break; - - /* Change nick on all channels */ - silc_hash_table_list(client_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - chat = purple_conversation_manager_find_chat(manager, sg->account, - chu->channel->channel_name); - if (!chat) { - continue; - } - if (purple_chat_conversation_has_user(PURPLE_CHAT_CONVERSATION(chat), client_entry->nickname)) { - purple_chat_conversation_rename_user(PURPLE_CHAT_CONVERSATION(chat), - tmp, name); - } - } - silc_hash_table_list_reset(&htl); - - break; - - case SILC_NOTIFY_TYPE_CMODE_CHANGE: - idtype = va_arg(va, int); - entry = va_arg(va, void *); - mode = va_arg(va, SilcUInt32); - (void)va_arg(va, char *); - (void)va_arg(va, char *); - (void)va_arg(va, char *); - (void)va_arg(va, SilcPublicKey); - (void)va_arg(va, SilcDList); - channel = va_arg(va, SilcChannelEntry); - - chat = purple_conversation_manager_find_chat(manager, sg->account, - channel->channel_name); - if (!chat) { - break; - } - - if (idtype == SILC_ID_CLIENT) { - name = ((SilcClientEntry)entry)->nickname; - } else if (idtype == SILC_ID_SERVER) { - name = ((SilcServerEntry)entry)->server_name; - } else { - name = ((SilcChannelEntry)entry)->channel_name; - } - - if (!name) { - break; - } - - if (mode) { - silcpurple_get_chmode_string(mode, buf2, sizeof(buf2)); - g_snprintf(buf, sizeof(buf), - _("<I>%s</I> set channel <I>%s</I> modes to: %s"), name, - channel->channel_name, buf2); - } else { - g_snprintf(buf, sizeof(buf), - _("<I>%s</I> removed all channel <I>%s</I> modes"), name, - channel->channel_name); - } - purple_conversation_write_system_message(PURPLE_CONVERSATION(chat), buf, 0); - break; - - case SILC_NOTIFY_TYPE_CUMODE_CHANGE: - { - PurpleChatUserFlags flags = PURPLE_CHAT_USER_NONE; - idtype = va_arg(va, int); - entry = va_arg(va, void *); - mode = va_arg(va, SilcUInt32); - client_entry2 = va_arg(va, SilcClientEntry); - channel = va_arg(va, SilcChannelEntry); - - chat = purple_conversation_manager_find_chat(manager, sg->account, - channel->channel_name); - if (!chat) { - break; - } - - if (idtype == SILC_ID_CLIENT) { - name = ((SilcClientEntry)entry)->nickname; - } else if (idtype == SILC_ID_SERVER) { - name = ((SilcServerEntry)entry)->server_name; - } else { - name = ((SilcChannelEntry)entry)->channel_name; - } - - if (!name) { - break; - } - - if (mode) { - silcpurple_get_chumode_string(mode, buf2, sizeof(buf2)); - g_snprintf(buf, sizeof(buf), - _("<I>%s</I> set <I>%s's</I> modes to: %s"), name, - client_entry2->nickname, buf2); - if (mode & SILC_CHANNEL_UMODE_CHANFO) - flags |= PURPLE_CHAT_USER_FOUNDER; - if (mode & SILC_CHANNEL_UMODE_CHANOP) - flags |= PURPLE_CHAT_USER_OP; - } else { - g_snprintf(buf, sizeof(buf), - _("<I>%s</I> removed all <I>%s's</I> modes"), name, - client_entry2->nickname); - } - purple_conversation_write_system_message(chat, buf, 0); - purple_chat_user_set_flags(purple_chat_conversation_find_user( - PURPLE_CHAT_CONVERSATION(chat), client_entry2->nickname), flags); - break; - } - - case SILC_NOTIFY_TYPE_MOTD: - tmp = va_arg(va, char *); - silc_free(sg->motd); - sg->motd = silc_memdup(tmp, strlen(tmp)); - break; - - case SILC_NOTIFY_TYPE_KICKED: - client_entry = va_arg(va, SilcClientEntry); - tmp = va_arg(va, char *); - client_entry2 = va_arg(va, SilcClientEntry); - channel = va_arg(va, SilcChannelEntry); - - chat = purple_conversation_manager_find_chat(manager, sg->account, - channel->channel_name); - if (!chat) { - break; - } - - if (client_entry == conn->local_entry) { - /* Remove us from channel */ - g_snprintf(buf, sizeof(buf), - _("You have been kicked off <I>%s</I> by <I>%s</I> (%s)"), - channel->channel_name, client_entry2->nickname, - tmp ? tmp : ""); - purple_conversation_write_system_message(chat, buf, 0); - purple_serv_got_chat_left(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(chat))); - } else { - /* Remove user from channel */ - g_snprintf(buf, sizeof(buf), _("Kicked by %s (%s)"), - client_entry2->nickname, tmp ? tmp : ""); - purple_chat_conversation_remove_user(PURPLE_CHAT_CONVERSATION(chat), - client_entry->nickname, - buf); - } - - break; - - case SILC_NOTIFY_TYPE_KILLED: - client_entry = va_arg(va, SilcClientEntry); - tmp = va_arg(va, char *); - idtype = va_arg(va, int); - entry = va_arg(va, SilcClientEntry); - - if (client_entry == conn->local_entry) { - if (idtype == SILC_ID_CLIENT) { - client_entry2 = (SilcClientEntry)entry; - g_snprintf(buf, sizeof(buf), - _("You have been killed by %s (%s)"), - client_entry2->nickname, tmp ? tmp : ""); - } else if (idtype == SILC_ID_SERVER) { - server_entry = (SilcServerEntry)entry; - g_snprintf(buf, sizeof(buf), - _("You have been killed by %s (%s)"), - server_entry->server_name, tmp ? tmp : ""); - } else if (idtype == SILC_ID_CHANNEL) { - channel = (SilcChannelEntry)entry; - g_snprintf(buf, sizeof(buf), - _("You have been killed by %s (%s)"), - channel->channel_name, tmp ? tmp : ""); - } - - /* Remove us from all channels */ - silc_hash_table_list(client_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - chat = purple_conversation_manager_find_chat(manager, sg->account, - chu->channel->channel_name); - if (!chat) { - continue; - } - purple_conversation_write_system_message(chat, buf, 0); - purple_serv_got_chat_left(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(chat))); - } - silc_hash_table_list_reset(&htl); - - } else { - if (idtype == SILC_ID_CLIENT) { - client_entry2 = (SilcClientEntry)entry; - g_snprintf(buf, sizeof(buf), - _("Killed by %s (%s)"), - client_entry2->nickname, tmp ? tmp : ""); - } else if (idtype == SILC_ID_SERVER) { - server_entry = (SilcServerEntry)entry; - g_snprintf(buf, sizeof(buf), - _("Killed by %s (%s)"), - server_entry->server_name, tmp ? tmp : ""); - } else if (idtype == SILC_ID_CHANNEL) { - channel = (SilcChannelEntry)entry; - g_snprintf(buf, sizeof(buf), - _("Killed by %s (%s)"), - channel->channel_name, tmp ? tmp : ""); - } - - /* Remove user from all channels */ - silc_hash_table_list(client_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - chat = purple_conversation_manager_find_chat(manager, sg->account, - chu->channel->channel_name); - if (!chat) { - continue; - } - purple_chat_conversation_remove_user(PURPLE_CHAT_CONVERSATION(chat), - client_entry->nickname, tmp); - } - silc_hash_table_list_reset(&htl); - } - - break; - - case SILC_NOTIFY_TYPE_CHANNEL_CHANGE: - break; - - case SILC_NOTIFY_TYPE_SERVER_SIGNOFF: - (void)va_arg(va, void *); - list = va_arg(va, SilcDList); - - silc_dlist_start(list); - while ((client_entry = silc_dlist_get(list))) { - /* Remove from all channels */ - silc_hash_table_list(client_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - chat = purple_conversation_manager_find_chat(manager, sg->account, - chu->channel->channel_name); - if (!chat) { - continue; - } - purple_chat_conversation_remove_user(PURPLE_CHAT_CONVERSATION(chat), - client_entry->nickname, - _("Server signoff")); - } - silc_hash_table_list_reset(&htl); - } - break; - - case SILC_NOTIFY_TYPE_ERROR: - { - SilcStatus error = va_arg(va, int); - purple_notify_error(gc, "Error Notify", - silc_get_status_message(error), - NULL, purple_request_cpar_from_connection(gc)); - } - break; - - case SILC_NOTIFY_TYPE_WATCH: - { - SilcPublicKey public_key; - unsigned char *pk; - SilcUInt32 pk_len; - char *fingerprint; - - client_entry = va_arg(va, SilcClientEntry); - (void)va_arg(va, char *); - mode = va_arg(va, SilcUInt32); - notify = va_arg(va, int); - public_key = va_arg(va, SilcPublicKey); - - b = NULL; - if (public_key) { - GSList *buddies; - const char *f; - gsize i; - - pk = silc_pkcs_public_key_encode(public_key, &pk_len); - if (!pk) - break; - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - for (i = 0; i < strlen(fingerprint); i++) - if (fingerprint[i] == ' ') - fingerprint[i] = '_'; - g_snprintf(buf, sizeof(buf) - 1, - "%s" G_DIR_SEPARATOR_S "clientkeys" - G_DIR_SEPARATOR_S "clientkey_%s.pub", - silcpurple_silcdir(), fingerprint); - silc_free(fingerprint); - silc_free(pk); - - /* Find buddy by associated public key */ - for (buddies = purple_blist_find_buddies(account, NULL); buddies; - buddies = g_slist_delete_link(buddies, buddies)) { - b = buddies->data; - f = purple_blist_node_get_string(PURPLE_BLIST_NODE(b), "public-key"); - if (purple_strequal(f, buf)) - goto cont; - b = NULL; - } - } - cont: - if (!b) { - /* Find buddy by nickname */ - b = purple_blist_find_buddy(sg->account, client_entry->nickname); - if (!b) { - purple_debug_warning("silc", "WATCH for %s, unknown buddy\n", - client_entry->nickname); - break; - } - } - - silc_free(purple_buddy_get_protocol_data(b)); - purple_buddy_set_protocol_data(b, silc_memdup(&client_entry->id, - sizeof(client_entry->id))); - if (notify == SILC_NOTIFY_TYPE_NICK_CHANGE) { - break; - } else if (notify == SILC_NOTIFY_TYPE_UMODE_CHANGE) { - /* See if client was away and is now present */ - if (!(mode & (SILC_UMODE_GONE | SILC_UMODE_INDISPOSED | - SILC_UMODE_BUSY | SILC_UMODE_PAGE | - SILC_UMODE_DETACHED)) && - (client_entry->mode & SILC_UMODE_GONE || - client_entry->mode & SILC_UMODE_INDISPOSED || - client_entry->mode & SILC_UMODE_BUSY || - client_entry->mode & SILC_UMODE_PAGE || - client_entry->mode & SILC_UMODE_DETACHED)) { - client_entry->mode = mode; - purple_protocol_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL); - } - else if ((mode & SILC_UMODE_GONE) || - (mode & SILC_UMODE_INDISPOSED) || - (mode & SILC_UMODE_BUSY) || - (mode & SILC_UMODE_PAGE) || - (mode & SILC_UMODE_DETACHED)) { - client_entry->mode = mode; - purple_protocol_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_OFFLINE, NULL); - } - } else if (notify == SILC_NOTIFY_TYPE_SIGNOFF || - notify == SILC_NOTIFY_TYPE_SERVER_SIGNOFF || - notify == SILC_NOTIFY_TYPE_KILLED) { - client_entry->mode = mode; - purple_protocol_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_OFFLINE, NULL); - } else if (notify == SILC_NOTIFY_TYPE_NONE) { - client_entry->mode = mode; - purple_protocol_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL); - } - } - break; - - default: - purple_debug_info("silc", "Unhandled notification: %d\n", type); - break; - } - - va_end(va); -} - - -/* Command handler. This function is called always after application has - called a command. It will be called to indicate that the command - was processed. It will also be called if error occurs while processing - the command. The `success' indicates whether the command was sent - or if error occurred. The `status' indicates the actual error. - The `argc' and `argv' are the command line arguments sent to the - command by application. Note that, this is not reply to the command - from server, this is merely and indication to application that the - command was processed. */ - -static void -silc_command(SilcClient client, SilcClientConnection conn, - SilcBool success, SilcCommand command, SilcStatus status, - SilcUInt32 argc, unsigned char **argv) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = purple_connection_get_protocol_data(gc); - - switch (command) { - - case SILC_COMMAND_CMODE: - if (argc == 3 && purple_strequal((char *)argv[2], "+C")) - sg->chpk = TRUE; - else - sg->chpk = FALSE; - break; - - default: - break; - } -} - - -/* Command reply handler. Delivers a reply to command that was sent - earlier. The `conn' is the associated client connection. The `command' - indicates the command reply type. If the `status' other than - SILC_STATUS_OK an error occurred. In this case the `error' will indicate - the error. It is possible to receive list of command replies and list - of errors. In this case the `status' will indicate it is an list entry - (the `status' is SILC_STATUS_LIST_START, SILC_STATUS_LIST_ITEM and/or - SILC_STATUS_LIST_END). - - The arguments received in `ap' are command specific. See a separate - documentation in the Toolkit Reference Manual for the command reply - arguments. */ - -static void -silc_command_reply(SilcClient client, SilcClientConnection conn, - SilcCommand command, SilcStatus status, - SilcStatus error, va_list ap) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = purple_connection_get_protocol_data(gc); - PurpleConversation *chat; - PurpleConversationManager *manager; - - manager = purple_conversation_manager_get_default(); - - switch (command) { - case SILC_COMMAND_JOIN: - { - SilcChannelEntry channel; - SilcHashTableList *user_list; - SilcChannelUser chu; - GList *users = NULL, *flags = NULL; - char tmp[256], *topic; - - if (status != SILC_STATUS_OK) { - purple_notify_error(gc, _("Join Chat"), _("Cannot join channel"), - silc_get_status_message(error), - purple_request_cpar_from_connection(gc)); - return; - } - - (void)va_arg(ap, char *); - channel = va_arg(ap, SilcChannelEntry); - (void)va_arg(ap, SilcUInt32); - user_list = va_arg(ap, SilcHashTableList *); - topic = va_arg(ap, char *); - - /* Add channel to Purple */ - channel->context = SILC_32_TO_PTR(++sg->channel_ids); - purple_serv_got_joined_chat(gc, sg->channel_ids, channel->channel_name); - chat = purple_conversation_manager_find_chat(manager, sg->account, - channel->channel_name); - if (!chat) { - return; - } - - /* Add all users to channel */ - while (silc_hash_table_get(user_list, NULL, (void *)&chu)) { - PurpleChatUserFlags f = PURPLE_CHAT_USER_NONE; - chu->context = SILC_32_TO_PTR(sg->channel_ids); - - if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) - f |= PURPLE_CHAT_USER_FOUNDER; - if (chu->mode & SILC_CHANNEL_UMODE_CHANOP) - f |= PURPLE_CHAT_USER_OP; - users = g_list_append(users, chu->client->nickname); - flags = g_list_append(flags, GINT_TO_POINTER(f)); - - if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) { - if (chu->client == conn->local_entry) - g_snprintf(tmp, sizeof(tmp), - _("You are channel founder on <I>%s</I>"), - channel->channel_name); - else - g_snprintf(tmp, sizeof(tmp), - _("Channel founder on <I>%s</I> is <I>%s</I>"), - channel->channel_name, chu->client->nickname); - - purple_conversation_write_system_message(chat, tmp, 0); - } - } - - purple_chat_conversation_add_users(PURPLE_CHAT_CONVERSATION(chat), - users, NULL, flags, FALSE); - g_list_free(users); - g_list_free(flags); - - /* Set topic */ - if(topic) { - purple_chat_conversation_set_topic(PURPLE_CHAT_CONVERSATION(chat), - NULL, topic); - } - - /* Set nick */ - purple_chat_conversation_set_nick(PURPLE_CHAT_CONVERSATION(chat), - conn->local_entry->nickname); - } - break; - - case SILC_COMMAND_LEAVE: - break; - - case SILC_COMMAND_USERS: - break; - - case SILC_COMMAND_WHOIS: - { - SilcUInt32 *user_modes; - SilcDList channels; - SilcClientEntry client_entry; - char tmp[1024]; - char *moodstr, *statusstr, *contactstr, *langstr, *devicestr, *tzstr, *geostr; - PurpleNotifyUserInfo *user_info; - - if (status != SILC_STATUS_OK) { - purple_notify_error(gc, _("User Information"), - _("Cannot get user information"), - silc_get_status_message(error), - purple_request_cpar_from_connection(gc)); - break; - } - - client_entry = va_arg(ap, SilcClientEntry); - (void)va_arg(ap, char *); - (void)va_arg(ap, char *); - (void)va_arg(ap, char *); - channels = va_arg(ap, SilcDList); - (void)va_arg(ap, SilcUInt32); - (void)va_arg(ap, SilcUInt32); /* idle */ - (void)va_arg(ap, unsigned char *); - user_modes = va_arg(ap, SilcUInt32 *); - - user_info = purple_notify_user_info_new(); - purple_notify_user_info_add_pair_plaintext(user_info, _("Nickname"), client_entry->nickname); - if (client_entry->realname) { - purple_notify_user_info_add_pair_plaintext(user_info, _("Real Name"), client_entry->realname); - } - if (*client_entry->hostname) { - gchar *tmp2; - tmp2 = g_strdup_printf("%s@%s", client_entry->username, client_entry->hostname); - purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), tmp2); - g_free(tmp2); - } else - purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), client_entry->username); - - if (client_entry->mode) { - memset(tmp, 0, sizeof(tmp)); - silcpurple_get_umode_string(client_entry->mode, - tmp, sizeof(tmp) - strlen(tmp)); - /* TODO: Check whether it's correct to call add_pair_html, - or if we should be using add_pair_plaintext */ - purple_notify_user_info_add_pair_html(user_info, _("User Modes"), tmp); - } - - silcpurple_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr); - if (moodstr) { - /* TODO: Check whether it's correct to call add_pair_html, - or if we should be using add_pair_plaintext */ - purple_notify_user_info_add_pair_html(user_info, _("Mood"), moodstr); - g_free(moodstr); - } - - if (statusstr) { - purple_notify_user_info_add_pair_plaintext(user_info, _("Status Text"), statusstr); - g_free(statusstr); - } - - if (contactstr) { - /* TODO: Check whether it's correct to call add_pair_html, - or if we should be using add_pair_plaintext */ - purple_notify_user_info_add_pair_html(user_info, _("Preferred Contact"), contactstr); - g_free(contactstr); - } - - if (langstr) { - /* TODO: Check whether it's correct to call add_pair_html, - or if we should be using add_pair_plaintext */ - purple_notify_user_info_add_pair_html(user_info, _("Preferred Language"), langstr); - g_free(langstr); - } - - if (devicestr) { - /* TODO: Check whether it's correct to call add_pair_html, - or if we should be using add_pair_plaintext */ - purple_notify_user_info_add_pair_html(user_info, _("Device"), devicestr); - g_free(devicestr); - } - - if (tzstr) { - /* TODO: Check whether it's correct to call add_pair_html, - or if we should be using add_pair_plaintext */ - purple_notify_user_info_add_pair_html(user_info, _("Timezone"), tzstr); - g_free(tzstr); - } - - if (geostr) { - /* TODO: Check whether it's correct to call add_pair_html, - or if we should be using add_pair_plaintext */ - purple_notify_user_info_add_pair_html(user_info, _("Geolocation"), geostr); - g_free(geostr); - } - - if (*client_entry->server) { - /* TODO: Check whether it's correct to call add_pair_html, - or if we should be using add_pair_plaintext */ - purple_notify_user_info_add_pair_html(user_info, _("Server"), client_entry->server); - } - - if (channels && user_modes) { - SilcChannelPayload entry; - int i = 0; - - memset(tmp, 0, sizeof(tmp)); - silc_dlist_start(channels); - while ((entry = silc_dlist_get(channels))) { - SilcUInt32 name_len; - char *m = silc_client_chumode_char(user_modes[i++]); - char *name = (char *)silc_channel_get_name(entry, &name_len); - if (m) - silc_strncat(tmp, sizeof(tmp) - 1, m, strlen(m)); - silc_strncat(tmp, sizeof(tmp) - 1, name, name_len); - silc_strncat(tmp, sizeof(tmp) - 1, " ", 1); - silc_free(m); - } - purple_notify_user_info_add_pair_plaintext(user_info, _("Currently on"), tmp); - } - - if (client_entry->public_key) { - char *fingerprint, *babbleprint; - unsigned char *pk; - SilcUInt32 pk_len; - pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len); - if (pk) { - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - purple_notify_user_info_add_pair_plaintext(user_info, _("Public Key Fingerprint"), fingerprint); - purple_notify_user_info_add_pair_plaintext(user_info, _("Public Key Babbleprint"), babbleprint); - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); - } - } - - purple_notify_userinfo(gc, client_entry->nickname, user_info, NULL, NULL); - purple_notify_user_info_destroy(user_info); - } - break; - - case SILC_COMMAND_WHOWAS: - { - SilcClientEntry client_entry; - char *nickname, *realname, *username; - PurpleNotifyUserInfo *user_info; - - if (status != SILC_STATUS_OK) { - purple_notify_error(gc, _("User Information"), - _("Cannot get user information"), - silc_get_status_message(error), - purple_request_cpar_from_connection(gc)); - break; - } - - client_entry = va_arg(ap, SilcClientEntry); - nickname = va_arg(ap, char *); - username = va_arg(ap, char *); - realname = va_arg(ap, char *); - if (!nickname) - break; - - user_info = purple_notify_user_info_new(); - purple_notify_user_info_add_pair_plaintext(user_info, _("Nickname"), nickname); - if (realname) - purple_notify_user_info_add_pair_plaintext(user_info, _("Real Name"), realname); - if (username) { - if (client_entry && *client_entry->hostname) { - gchar *tmp; - tmp = g_strdup_printf("%s@%s", username, client_entry->hostname); - purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), tmp); - g_free(tmp); - } else - purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), username); - } - if (client_entry && *client_entry->server) { - /* TODO: Check whether it's correct to call add_pair_html, - or if we should be using add_pair_plaintext */ - purple_notify_user_info_add_pair_html(user_info, _("Server"), client_entry->server); - } - - - if (client_entry && client_entry->public_key) { - char *fingerprint, *babbleprint; - unsigned char *pk; - SilcUInt32 pk_len; - pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len); - if (pk) { - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - purple_notify_user_info_add_pair_plaintext(user_info, _("Public Key Fingerprint"), fingerprint); - purple_notify_user_info_add_pair_plaintext(user_info, _("Public Key Babbleprint"), babbleprint); - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); - } - } - - purple_notify_userinfo(gc, nickname, user_info, NULL, NULL); - purple_notify_user_info_destroy(user_info); - } - break; - - case SILC_COMMAND_DETACH: - { - const char *file; - SilcBuffer detach_data; - - if (status != SILC_STATUS_OK) { - purple_notify_error(gc, _("Detach From Server"), _("Cannot detach"), - silc_get_status_message(error), - purple_request_cpar_from_connection(gc)); - return; - } - - detach_data = va_arg(ap, SilcBuffer); - - /* Save the detachment data to file. */ - file = silcpurple_session_file(purple_account_get_username(sg->account)); - g_unlink(file); - silc_file_writefile(file, (const char *)silc_buffer_data(detach_data), - silc_buffer_len(detach_data)); - } - break; - - case SILC_COMMAND_TOPIC: - { - SilcChannelEntry channel; - - if (status != SILC_STATUS_OK) { - purple_notify_error(gc, _("Topic"), _("Cannot set topic"), - silc_get_status_message(error), - purple_request_cpar_from_connection(gc)); - return; - } - - channel = va_arg(ap, SilcChannelEntry); - - chat = purple_conversation_manager_find_chat(manager, sg->account, - channel->channel_name); - if (!chat) { - purple_debug_error("silc", "Got a topic for %s, which doesn't exist\n", - channel->channel_name); - break; - } - - /* Set topic */ - if (channel->topic) { - purple_chat_conversation_set_topic(PURPLE_CHAT_CONVERSATION(chat), - NULL, channel->topic); - } - } - break; - - case SILC_COMMAND_NICK: - { - SilcClientEntry local_entry; - SilcHashTableList htl; - SilcChannelUser chu; - const char *oldnick, *newnick; - - if (status != SILC_STATUS_OK) { - purple_notify_error(gc, _("Nick"), _("Failed to change nickname"), - silc_get_status_message(error), - purple_request_cpar_from_connection(gc)); - return; - } - - local_entry = va_arg(ap, SilcClientEntry); - newnick = va_arg(ap, char *); - - /* Change nick on all channels */ - silc_hash_table_list(local_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - chat = purple_conversation_manager_find_chat(manager, sg->account, - chu->channel->channel_name); - if (!chat) { - continue; - } - oldnick = purple_chat_conversation_get_nick(PURPLE_CHAT_CONVERSATION(chat)); - if (!purple_strequal(oldnick, - purple_normalize(purple_conversation_get_account(chat), - newnick))) - { - - purple_chat_conversation_rename_user(PURPLE_CHAT_CONVERSATION(chat), - oldnick, newnick); - purple_chat_conversation_set_nick(PURPLE_CHAT_CONVERSATION(chat), newnick); - } - } - silc_hash_table_list_reset(&htl); - - purple_connection_set_display_name(gc, newnick); - } - break; - - case SILC_COMMAND_LIST: - { - char *topic, *name; - int usercount; - PurpleRoomlistRoom *room; - - if (sg->roomlist_cancelled) - break; - - if (error != SILC_STATUS_OK) { - purple_notify_error(gc, _("Error"), _("Error retrieving room list"), - silc_get_status_message(error), - purple_request_cpar_from_connection(gc)); - purple_roomlist_set_in_progress(sg->roomlist, FALSE); - g_object_unref(sg->roomlist); - sg->roomlist = NULL; - return; - } - - (void)va_arg(ap, SilcChannelEntry); - name = va_arg(ap, char *); - if (!name) { - purple_notify_error(gc, _("Roomlist"), _("Cannot get room list"), - _("Network is empty"), - purple_request_cpar_from_connection(gc)); - purple_roomlist_set_in_progress(sg->roomlist, FALSE); - g_object_unref(sg->roomlist); - sg->roomlist = NULL; - return; - } - topic = va_arg(ap, char *); - usercount = va_arg(ap, int); - - room = purple_roomlist_room_new(name, topic); - purple_roomlist_room_set_user_count(room, usercount); - purple_roomlist_room_add_field(room, "channel", g_strdup(name)); - purple_roomlist_room_add(sg->roomlist, room); - g_object_unref(room); - - if (status == SILC_STATUS_LIST_END || - status == SILC_STATUS_OK) { - purple_roomlist_set_in_progress(sg->roomlist, FALSE); - g_object_unref(sg->roomlist); - sg->roomlist = NULL; - } - } - break; - - case SILC_COMMAND_GETKEY: - { - SilcPublicKey public_key; - - if (status != SILC_STATUS_OK) { - purple_notify_error(gc, _("Get Public Key"), - _("Cannot fetch the public key"), - silc_get_status_message(error), - purple_request_cpar_from_connection(gc)); - return; - } - - (void)va_arg(ap, SilcUInt32); - (void)va_arg(ap, void *); - public_key = va_arg(ap, SilcPublicKey); - - if (!public_key) - purple_notify_error(gc, _("Get Public Key"), - _("Cannot fetch the public key"), - _("No public key was received"), - purple_request_cpar_from_connection(gc)); - } - break; - - case SILC_COMMAND_INFO: - { - - char *server_name; - char *server_info; - char tmp[256]; - - if (status != SILC_STATUS_OK) { - purple_notify_error(gc, _("Server Information"), - _("Cannot get server information"), - silc_get_status_message(error), - purple_request_cpar_from_connection(gc)); - return; - } - - (void)va_arg(ap, SilcServerEntry); - server_name = va_arg(ap, char *); - server_info = va_arg(ap, char *); - - if (server_name && server_info) { - g_snprintf(tmp, sizeof(tmp), "Server: %s\n%s", - server_name, server_info); - purple_notify_info(gc, NULL, _("Server Information"), tmp, - purple_request_cpar_from_connection(gc)); - } - } - break; - - case SILC_COMMAND_STATS: - { - SilcClientStats *stats; - char *msg; - - if (status != SILC_STATUS_OK) { - purple_notify_error(gc, _("Server Statistics"), - _("Cannot get server statistics"), - silc_get_status_message(error), - purple_request_cpar_from_connection(gc)); - return; - } - - stats = va_arg(ap, SilcClientStats *); - - msg = g_strdup_printf(_("Local server start time: %s\n" - "Local server uptime: %s\n" - "Local server clients: %d\n" - "Local server channels: %d\n" - "Local server operators: %d\n" - "Local router operators: %d\n" - "Local cell clients: %d\n" - "Local cell channels: %d\n" - "Local cell servers: %d\n" - "Total clients: %d\n" - "Total channels: %d\n" - "Total servers: %d\n" - "Total routers: %d\n" - "Total server operators: %d\n" - "Total router operators: %d\n"), - silc_time_string(stats->starttime), - purple_str_seconds_to_string((int)stats->uptime), - (int)stats->my_clients, - (int)stats->my_channels, - (int)stats->my_server_ops, - (int)stats->my_router_ops, - (int)stats->cell_clients, - (int)stats->cell_channels, - (int)stats->cell_servers, - (int)stats->clients, - (int)stats->channels, - (int)stats->servers, - (int)stats->routers, - (int)stats->server_ops, - (int)stats->router_ops); - - purple_notify_info(gc, NULL, - _("Network Statistics"), msg, - purple_request_cpar_from_connection(gc)); - g_free(msg); - } - break; - - case SILC_COMMAND_PING: - { - if (status != SILC_STATUS_OK) { - purple_notify_error(gc, _("Ping"), _("Ping failed"), - silc_get_status_message(error), - purple_request_cpar_from_connection(gc)); - return; - } - - purple_notify_info(gc, _("Ping"), _("Ping reply received from server"), - NULL, purple_request_cpar_from_connection(gc)); - } - break; - - case SILC_COMMAND_KILL: - if (status != SILC_STATUS_OK) { - purple_notify_error(gc, _("Kill User"), - _("Could not kill user"), - silc_get_status_message(error), - purple_request_cpar_from_connection(gc)); - return; - } - break; - - case SILC_COMMAND_CMODE: - { - SilcChannelEntry channel_entry; - SilcDList channel_pubkeys, list; - SilcArgumentDecodedList e; - - if (status != SILC_STATUS_OK) - return; - - channel_entry = va_arg(ap, SilcChannelEntry); - (void)va_arg(ap, SilcUInt32); - (void)va_arg(ap, SilcPublicKey); - channel_pubkeys = va_arg(ap, SilcDList); - - if (!sg->chpk) - break; - - list = silc_dlist_init(); - - if (channel_pubkeys) { - silc_dlist_start(channel_pubkeys); - while ((e = silc_dlist_get(channel_pubkeys))) { - if (e->arg_type == 0x00 || - e->arg_type == 0x03) - silc_dlist_add(list, silc_pkcs_public_key_copy(e->argument)); - } - } - silcpurple_chat_chauth_show(sg, channel_entry, list); - } - break; - - case SILC_COMMAND_WATCH: - if (status != SILC_STATUS_OK) { - purple_notify_error(gc, _("WATCH"), _("Cannot watch user"), - silc_get_status_message(error), - purple_request_cpar_from_connection(gc)); - return; - } - break; - - default: - if (status == SILC_STATUS_OK) - purple_debug_info("silc", "Unhandled command: %d (succeeded)\n", command); - else - purple_debug_info("silc", "Unhandled command: %d (failed: %s)\n", command, - silc_get_status_message(error)); - break; - } -} - -/* Generic command reply callback for silc_client_command_send. Simply - calls the default command_reply client operation callback */ - -SilcBool silcpurple_command_reply(SilcClient client, SilcClientConnection conn, - SilcCommand command, SilcStatus status, - SilcStatus error, void *context, va_list ap) -{ - silc_command_reply(client, conn, command, status, error, ap); - return TRUE; -} - - -typedef struct { - union { - SilcAskPassphrase ask_pass; - SilcGetAuthMeth get_auth; - } u; - void *context; -} *SilcPurpleAskPassphrase; - -static void -silc_ask_auth_password_cb(const unsigned char *passphrase, - SilcUInt32 passphrase_len, void *context) -{ - SilcPurpleAskPassphrase internal = context; - - if (!passphrase || !(*passphrase)) - internal->u.get_auth(SILC_AUTH_NONE, NULL, 0, internal->context); - else - internal->u.get_auth(SILC_AUTH_PASSWORD, - (unsigned char *)passphrase, - passphrase_len, internal->context); - silc_free(internal); -} - -/* Find authentication method and authentication data by hostname and - port. The hostname may be IP address as well. The `auth_method' is - the authentication method the remote connection requires. It is - however possible that remote accepts also some other authentication - method. Application should use the method that may have been - configured for this connection. If none has been configured it should - use the required `auth_method'. If the `auth_method' is - SILC_AUTH_NONE, server does not require any authentication or the - required authentication method is not known. The `completion' - callback must be called to deliver the chosen authentication method - and data. The `conn' may be NULL. */ - -static void -silc_get_auth_method(SilcClient client, SilcClientConnection conn, - char *hostname, SilcUInt16 port, - SilcAuthMethod auth_method, - SilcGetAuthMeth completion, void *context) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcPurpleAskPassphrase internal; - const char *password; - - /* Check configuration if we have this connection configured. */ - if (auth_method == SILC_AUTH_PUBLIC_KEY && - purple_account_get_bool(sg->account, "pubkey-auth", FALSE)) { - completion(SILC_AUTH_PUBLIC_KEY, NULL, 0, context); - return; - } - if (auth_method == SILC_AUTH_PASSWORD) { - password = purple_connection_get_password(gc); - if (password && *password) { - completion(SILC_AUTH_PASSWORD, (unsigned char *)password, strlen(password), context); - return; - } - - /* Ask password from user */ - internal = silc_calloc(1, sizeof(*internal)); - if (!internal) - return; - internal->u.get_auth = completion; - internal->context = context; - silc_ask_passphrase(client, conn, silc_ask_auth_password_cb, - internal); - return; - } - - completion(SILC_AUTH_NONE, NULL, 0, context); -} - - -/* Called to verify received public key. The `conn_type' indicates which - entity (server or client) has sent the public key. If user decides to - trust the key the application may save the key as trusted public key for - later use. The `completion' must be called after the public key has - been verified. */ - -static void -silc_verify_public_key(SilcClient client, SilcClientConnection conn, - SilcConnectionType conn_type, - SilcPublicKey public_key, - SilcVerifyPublicKey completion, void *context) -{ - /* Verify public key */ - silcpurple_verify_public_key(client, conn, NULL, conn_type, - public_key, completion, context); -} - -static void -silc_ask_passphrase_cb(SilcPurpleAskPassphrase internal, const char *passphrase) -{ - if (!passphrase || !(*passphrase)) - internal->u.ask_pass(NULL, 0, internal->context); - else - internal->u.ask_pass((unsigned char *)passphrase, - strlen(passphrase), internal->context); - silc_free(internal); -} - -/* Ask (interact, that is) a passphrase from user. The passphrase is - returned to the library by calling the `completion' callback with - the `context'. The returned passphrase SHOULD be in UTF-8 encoded, - if not then the library will attempt to encode. */ - -static void -silc_ask_passphrase(SilcClient client, SilcClientConnection conn, - SilcAskPassphrase completion, void *context) -{ - PurpleConnection *gc = client->application; - SilcPurpleAskPassphrase internal = silc_calloc(1, sizeof(*internal)); - - if (!internal) - return; - internal->u.ask_pass = completion; - internal->context = context; - purple_request_input(gc, _("Passphrase"), NULL, - _("Passphrase required"), NULL, FALSE, TRUE, NULL, - _("OK"), G_CALLBACK(silc_ask_passphrase_cb), - _("Cancel"), G_CALLBACK(silc_ask_passphrase_cb), - purple_request_cpar_from_connection(gc), internal); -} - - -/* Called to indicate that incoming key agreement request has been - received. If the application wants to perform key agreement it may - call silc_client_perform_key_agreement to initiate key agreement or - silc_client_send_key_agreement to provide connection point to the - remote client in case the `hostname' is NULL. If key agreement is - not desired this request can be ignored. The `protocol' is either - value 0 for TCP or value 1 for UDP. */ - -static void -silc_key_agreement(SilcClient client, SilcClientConnection conn, - SilcClientEntry client_entry, - const char *hostname, SilcUInt16 protocol, - SilcUInt16 port) -{ - silcpurple_buddy_keyagr_request(client, conn, client_entry, - hostname, port, protocol); -} - - -/* Notifies application that file transfer protocol session is being - requested by the remote client indicated by the `client_entry' from - the `hostname' and `port'. The `session_id' is the file transfer - session and it can be used to either accept or reject the file - transfer request, by calling the silc_client_file_receive or - silc_client_file_close, respectively. */ - -static void -silc_ftp(SilcClient client, SilcClientConnection conn, - SilcClientEntry client_entry, SilcUInt32 session_id, - const char *hostname, SilcUInt16 port) -{ - silcpurple_ftp_request(client, conn, client_entry, session_id, - hostname, port); -} - -SilcClientOperations ops = { - silc_say, - silc_channel_message, - silc_private_message, - silc_notify, - silc_command, - silc_command_reply, - silc_get_auth_method, - silc_verify_public_key, - silc_ask_passphrase, - silc_key_agreement, - silc_ftp -}; diff --git a/libpurple/protocols/silc/pk.c b/libpurple/protocols/silc/pk.c deleted file mode 100644 index c51959d266..0000000000 --- a/libpurple/protocols/silc/pk.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - - silcpurple_pk.c - - Author: Pekka Riikonen <priikone@silcnet.org> - - Copyright (C) 2004 - 2007 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. - -*/ - -#include <glib/gi18n-lib.h> -#include <glib/gstdio.h> - -#include "glibcompat.h" /* for purple_g_stat on win32 */ -#include "silcpurple.h" - -/************************* Public Key Verification ***************************/ - -typedef struct { - SilcClient client; - SilcClientConnection conn; - char *filename; - char *entity; - char *entity_name; - char *fingerprint; - char *babbleprint; - SilcPublicKey public_key; - SilcVerifyPublicKey completion; - void *context; - gboolean changed; -} *PublicKeyVerify; - -static void silcpurple_verify_ask(const char *entity, - const char *fingerprint, - const char *babbleprint, - PublicKeyVerify verify); - -static void silcpurple_verify_cb(PublicKeyVerify verify, gint id) -{ - if (id != 2) { - if (verify->completion) - verify->completion(FALSE, verify->context); - } else { - if (verify->completion) - verify->completion(TRUE, verify->context); - - /* Save the key for future checking */ - silc_pkcs_save_public_key(verify->filename, verify->public_key, - SILC_PKCS_FILE_BASE64); - } - - g_free(verify->filename); - g_free(verify->entity); - g_free(verify->entity_name); - silc_free(verify->fingerprint); - silc_free(verify->babbleprint); - silc_pkcs_public_key_free(verify->public_key); - silc_free(verify); -} - -static void silcpurple_verify_details_cb(PublicKeyVerify verify) -{ - /* What a hack. We have to display the accept dialog _again_ - because Purple closes the dialog after you press the button. Purple - should have option for the dialogs whether the buttons close them - or not. */ - silcpurple_verify_ask(verify->entity, verify->fingerprint, - verify->babbleprint, verify); -} - -static void silcpurple_verify_details(PublicKeyVerify verify, gint id) -{ - PurpleConnection *gc = verify->client->application; - SilcPurple sg = purple_connection_get_protocol_data(gc); - - silcpurple_show_public_key(sg, verify->entity_name, verify->public_key, - G_CALLBACK(silcpurple_verify_details_cb), - verify); -} - -static void silcpurple_verify_ask(const char *entity, - const char *fingerprint, - const char *babbleprint, - PublicKeyVerify verify) -{ - PurpleConnection *gc = verify->client->application; - char tmp[256], tmp2[256]; - - if (verify->changed) { - g_snprintf(tmp, sizeof(tmp), - _("Received %s's public key. Your local copy does not match this " - "key. Would you still like to accept this public key?"), - entity); - } else { - g_snprintf(tmp, sizeof(tmp), - _("Received %s's public key. Would you like to accept this " - "public key?"), entity); - } - g_snprintf(tmp2, sizeof(tmp2), - _("Fingerprint and babbleprint for the %s key are:\n\n" - "%s\n%s\n"), entity, fingerprint, babbleprint); - - purple_request_action(gc, _("Verify Public Key"), tmp, tmp2, - PURPLE_DEFAULT_ACTION_NONE, - purple_request_cpar_from_connection(gc), verify, 3, - _("Yes"), G_CALLBACK(silcpurple_verify_cb), - _("No"), G_CALLBACK(silcpurple_verify_cb), - _("_View..."), G_CALLBACK(silcpurple_verify_details)); -} - -void silcpurple_verify_public_key(SilcClient client, SilcClientConnection conn, - const char *name, SilcConnectionType conn_type, - SilcPublicKey public_key, - SilcVerifyPublicKey completion, void *context) -{ - PurpleConnection *gc = client->application; - gsize i; - char file[256], filename[256], filename2[256], *ipf, *hostf = NULL; - char *fingerprint, *babbleprint; - struct passwd *pw; - GStatBuf st; - char *entity = ((conn_type == SILC_CONN_SERVER || - conn_type == SILC_CONN_ROUTER) ? - "server" : "client"); - PublicKeyVerify verify; - const char *ip, *hostname; - SilcUInt16 port; - unsigned char *pk; - SilcUInt32 pk_len; - - if (silc_pkcs_get_type(public_key) != SILC_PKCS_SILC) { - purple_notify_error(gc, _("Verify Public Key"), - _("Unsupported public key type"), NULL, - purple_request_cpar_from_connection(gc)); - if (completion) - completion(FALSE, context); - return; - } - - pw = getpwuid(getuid()); - if (!pw) { - if (completion) - completion(FALSE, context); - return; - } - - memset(filename, 0, sizeof(filename)); - memset(filename2, 0, sizeof(filename2)); - memset(file, 0, sizeof(file)); - - silc_socket_stream_get_info(silc_packet_stream_get_stream(conn->stream), - NULL, &hostname, &ip, &port); - - pk = silc_pkcs_public_key_encode(public_key, &pk_len); - if (!pk) { - if (completion) - completion(FALSE, context); - return; - } - - if (conn_type == SILC_CONN_SERVER || - conn_type == SILC_CONN_ROUTER) { - if (!name) { - g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity, - ip, port); - g_snprintf(filename, sizeof(filename) - 1, - "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s", - silcpurple_silcdir(), entity, file); - - g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity, - hostname, port); - g_snprintf(filename2, sizeof(filename2) - 1, - "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s", - silcpurple_silcdir(), entity, file); - - ipf = filename; - hostf = filename2; - } else { - g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity, - name, port); - g_snprintf(filename, sizeof(filename) - 1, - "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s", - silcpurple_silcdir(), entity, file); - - ipf = filename; - } - } else { - /* Replace all whitespaces with `_'. */ - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - for (i = 0; i < strlen(fingerprint); i++) - if (fingerprint[i] == ' ') - fingerprint[i] = '_'; - - g_snprintf(file, sizeof(file) - 1, "%skey_%s.pub", entity, fingerprint); - g_snprintf(filename, sizeof(filename) - 1, - "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s", - silcpurple_silcdir(), entity, file); - silc_free(fingerprint); - - ipf = filename; - } - - verify = silc_calloc(1, sizeof(*verify)); - if (!verify) - return; - verify->client = client; - verify->conn = conn; - verify->filename = g_strdup(ipf); - verify->entity = g_strdup(entity); - verify->entity_name = (conn_type != SILC_CONN_CLIENT ? - (name ? g_strdup(name) : g_strdup(hostname)) - : NULL); - verify->public_key = silc_pkcs_public_key_copy(public_key); - verify->completion = completion; - verify->context = context; - fingerprint = verify->fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = verify->babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - - /* Check whether this key already exists */ - if (g_stat(ipf, &st) < 0 && (!hostf || g_stat(hostf, &st) < 0)) { - /* Key does not exist, ask user to verify the key and save it */ - silcpurple_verify_ask(name ? name : entity, - fingerprint, babbleprint, verify); - return; - } else { - /* The key already exists, verify it. */ - SilcPublicKey public_key; - unsigned char *encpk; - SilcUInt32 encpk_len; - - /* Load the key file, try for both IP filename and hostname filename */ - if (!silc_pkcs_load_public_key(ipf, &public_key) && - (!hostf || (!silc_pkcs_load_public_key(hostf, &public_key)))) { - silcpurple_verify_ask(name ? name : entity, - fingerprint, babbleprint, verify); - return; - } - - /* Encode the key data */ - encpk = silc_pkcs_public_key_encode(public_key, &encpk_len); - if (!encpk) { - silcpurple_verify_ask(name ? name : entity, - fingerprint, babbleprint, verify); - return; - } - - /* Compare the keys */ - if (memcmp(encpk, pk, encpk_len)) { - /* Ask user to verify the key and save it */ - verify->changed = TRUE; - silcpurple_verify_ask(name ? name : entity, - fingerprint, babbleprint, verify); - return; - } - - /* Local copy matched */ - if (completion) - completion(TRUE, context); - g_free(verify->filename); - g_free(verify->entity); - g_free(verify->entity_name); - silc_free(verify->fingerprint); - silc_free(verify->babbleprint); - silc_pkcs_public_key_free(verify->public_key); - silc_free(verify); - } -} diff --git a/libpurple/protocols/silc/resources/icons/16x16/apps/im-silc.png b/libpurple/protocols/silc/resources/icons/16x16/apps/im-silc.png Binary files differdeleted file mode 100644 index 3469ed197b..0000000000 --- a/libpurple/protocols/silc/resources/icons/16x16/apps/im-silc.png +++ /dev/null diff --git a/libpurple/protocols/silc/resources/icons/16x16/apps/scalable/im-silc.svg b/libpurple/protocols/silc/resources/icons/16x16/apps/scalable/im-silc.svg deleted file mode 100644 index 70a2047adb..0000000000 --- a/libpurple/protocols/silc/resources/icons/16x16/apps/scalable/im-silc.svg +++ /dev/null @@ -1,173 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:xlink="http://www.w3.org/1999/xlink" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="16px" - height="16px" - id="svg4248" - sodipodi:version="0.32" - inkscape:version="0.46" - sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/16/scalable" - sodipodi:docname="silc.svg" - inkscape:export-filename="/home/hbons/Bureaublad/silc.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - inkscape:output_extension="org.inkscape.output.svg.inkscape"> - <defs - id="defs4250"> - <linearGradient - inkscape:collect="always" - id="linearGradient8658"> - <stop - style="stop-color:#ffffff;stop-opacity:1;" - offset="0" - id="stop8660" /> - <stop - style="stop-color:#ffffff;stop-opacity:0;" - offset="1" - id="stop8662" /> - </linearGradient> - <linearGradient - id="linearGradient8641"> - <stop - style="stop-color:#ccf4a7;stop-opacity:1" - offset="0" - id="stop8643" /> - <stop - style="stop-color:#73d216;stop-opacity:1" - offset="1" - id="stop8645" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient8633"> - <stop - style="stop-color:#346a02;stop-opacity:1;" - offset="0" - id="stop8635" /> - <stop - style="stop-color:#54ac02;stop-opacity:1" - offset="1" - id="stop8637" /> - </linearGradient> - <linearGradient - id="linearGradient2222" - inkscape:collect="always"> - <stop - id="stop2224" - offset="0" - style="stop-color:#8ae234;stop-opacity:1;" /> - <stop - id="stop2226" - offset="1" - style="stop-color:#8ae234;stop-opacity:0;" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient2222" - id="linearGradient5731" - gradientUnits="userSpaceOnUse" - x1="13.638538" - y1="11.020223" - x2="13.638538" - y2="-28.749279" - gradientTransform="matrix(0.797619,0,0,0.940287,-21.494048,-2.875489)" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient2222" - id="linearGradient5739" - gradientUnits="userSpaceOnUse" - x1="13.638538" - y1="11.020223" - x2="13.638538" - y2="-28.749279" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient8633" - id="linearGradient8639" - x1="10.13271" - y1="9.9967499" - x2="7.509789" - y2="6.4700642" - gradientUnits="userSpaceOnUse" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient8641" - id="linearGradient8647" - x1="4.010623" - y1="5.2489076" - x2="10.514683" - y2="11.829373" - gradientUnits="userSpaceOnUse" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient8658" - id="linearGradient8664" - x1="3.8175509" - y1="5.2679143" - x2="10.938335" - y2="10.646874" - gradientUnits="userSpaceOnUse" /> - </defs> - <sodipodi:namedview - id="base" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageopacity="0.0" - inkscape:pageshadow="2" - inkscape:zoom="27.3287" - inkscape:cx="21.250133" - inkscape:cy="8.5563256" - inkscape:current-layer="layer1" - showgrid="true" - inkscape:grid-bbox="true" - inkscape:document-units="px" - inkscape:window-width="1440" - inkscape:window-height="847" - inkscape:window-x="0" - inkscape:window-y="0" - inkscape:snap-bbox="true" - inkscape:snap-nodes="false" - objecttolerance="10" - gridtolerance="10"> - <inkscape:grid - type="xygrid" - id="grid8623" - visible="true" - enabled="true" /> - </sodipodi:namedview> - <metadata - id="metadata4253"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - </cc:Work> - </rdf:RDF> - </metadata> - <g - id="layer1" - inkscape:label="Layer 1" - inkscape:groupmode="layer"> - <path - style="opacity:1;fill:url(#linearGradient8647);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient8639);stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="M 7.4939374,1.4832176 C 6.9292248,1.4832176 6.489473,1.9229695 6.489473,2.487682 L 6.489473,11.522046 L 1.5714286,11.522046 C 0.98499647,11.522046 0.5,12.007042 0.5,12.593475 L 0.5,13.445354 C 0.5,14.031787 0.98499647,14.516783 1.5714286,14.516783 L 8.4398609,14.516783 C 9.0262932,14.516783 9.5112895,14.031787 9.5112895,13.445354 L 9.5112895,4.4905103 L 14.495536,4.4905103 C 15.060249,4.4905103 15.500001,4.0507584 15.500001,3.4860459 L 15.500001,2.487682 C 15.500001,1.9229694 15.060249,1.4832176 14.495536,1.4832176 L 7.4939374,1.4832176 z" - id="rect8625" - sodipodi:nodetypes="ccccccccccccccc" /> - <path - style="opacity:1;fill:url(#linearGradient8664);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" - d="M 7.5,2.0000003 C 7.2189639,2.0000003 7,2.2189642 7,2.5000003 L 7,12 L 1.5,12 C 1.2189639,12 1,12.223 1,12.5 C 1,12.777 1.2189639,13 1.5,13 L 7.5,13 C 7.5604228,13 7.6338463,12.987963 7.6875,12.96875 C 7.7482316,12.943516 7.7979041,12.888938 7.84375,12.84375 C 7.8975454,12.794761 7.9400258,12.755638 7.96875,12.6875 C 7.9943521,12.627641 8,12.56925 8,12.5 L 8,3.0000003 L 14.5,3.0000003 C 14.781036,3.0000003 15,2.7810364 15,2.5000003 C 15,2.2189642 14.781036,2.0000003 14.5,2.0000003 C 12.16669,1.9999996 9.8332346,2.0000003 7.5,2.0000003 z" - id="rect8649" - sodipodi:nodetypes="ccccsccssscccscc" /> - </g> -</svg> diff --git a/libpurple/protocols/silc/resources/icons/22x22/apps/im-silc.png b/libpurple/protocols/silc/resources/icons/22x22/apps/im-silc.png Binary files differdeleted file mode 100644 index 54a54ab012..0000000000 --- a/libpurple/protocols/silc/resources/icons/22x22/apps/im-silc.png +++ /dev/null diff --git a/libpurple/protocols/silc/resources/icons/22x22/apps/scalable/im-silc.svg b/libpurple/protocols/silc/resources/icons/22x22/apps/scalable/im-silc.svg deleted file mode 100644 index cec38a7a1c..0000000000 --- a/libpurple/protocols/silc/resources/icons/22x22/apps/scalable/im-silc.svg +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:xlink="http://www.w3.org/1999/xlink" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="24" - height="24" - id="svg2" - sodipodi:version="0.32" - inkscape:version="0.46" - version="1.0" - sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh" - sodipodi:docname="silc.svg" - inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/silc.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - inkscape:output_extension="org.inkscape.output.svg.inkscape"> - <defs - id="defs4"> - <linearGradient - inkscape:collect="always" - id="linearGradient2222"> - <stop - style="stop-color:#8ae234;stop-opacity:1;" - offset="0" - id="stop2224" /> - <stop - style="stop-color:#8ae234;stop-opacity:0;" - offset="1" - id="stop2226" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient3150"> - <stop - style="stop-color:#2e3436;stop-opacity:1;" - offset="0" - id="stop3152" /> - <stop - style="stop-color:#2e3436;stop-opacity:0;" - offset="1" - id="stop3154" /> - </linearGradient> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient3150" - id="radialGradient3156" - cx="10.748654" - cy="10.457643" - fx="10.748654" - fy="10.457643" - r="6.6449099" - gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)" - gradientUnits="userSpaceOnUse" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient2222" - id="linearGradient2228" - x1="14.315197" - y1="11.002394" - x2="13.638538" - y2="-28.749279" - gradientUnits="userSpaceOnUse" /> - </defs> - <sodipodi:namedview - id="base" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageopacity="0.0" - inkscape:pageshadow="2" - inkscape:zoom="7.3892443" - inkscape:cx="17.369816" - inkscape:cy="12.086934" - inkscape:document-units="px" - inkscape:current-layer="layer1" - showgrid="true" - fill="#9db029" - showguides="true" - inkscape:guide-bbox="true" - inkscape:window-width="1268" - inkscape:window-height="971" - inkscape:window-x="6" - inkscape:window-y="21" /> - <metadata - id="metadata7"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - </cc:Work> - </rdf:RDF> - </metadata> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1"> - <path - sodipodi:type="arc" - style="opacity:0.35;fill:url(#radialGradient3156);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="path3140" - sodipodi:cx="10.748654" - sodipodi:cy="10.457643" - sodipodi:rx="6.6449099" - sodipodi:ry="2.3675451" - d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1 4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1 17.393564 10.457643 z" - transform="matrix(1.655403,0,0,1.300982,-5.793351,5.474929)" /> - <path - style="opacity:1;fill:url(#linearGradient2228);fill-opacity:1.0;stroke:#4e9a06;stroke-width:0.99999964;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="M 10.494577,6.2547874 C 10.494577,6.7069733 10.550854,14.667436 10.504973,15.531249 C 10.504973,15.531249 4.6361995,15.499999 4.5312498,15.499999 C 3.411786,15.499999 2.4999998,16.35618 2.4999998,17.526317 C 2.4999998,18.690466 3.411786,19.504787 4.5312498,19.504787 L 11.27063,19.504787 C 13.660042,19.504787 14.5625,18.376459 14.5625,16.754787 C 14.5625,16.302601 14.434213,7.3539406 14.486856,6.5047874 C 14.486856,6.5047874 20.224476,6.5047874 20.574309,6.5047874 C 21.693773,6.5047874 22.635012,5.5969416 22.635012,4.430623 C 22.635012,3.6010066 21.693772,2.4999998 20.574309,2.4999998 L 13.59375,2.4999998 C 12.029203,2.4999998 10.494577,3.5345411 10.494577,6.2547874 z " - id="rect3167" - sodipodi:nodetypes="ccssscscssscs" /> - <path - sodipodi:type="inkscape:offset" - inkscape:radius="-1.0003172" - inkscape:original="M 13.59375 2.5 C 12.029203 2.5 10.5 3.5297537 10.5 6.25 C 10.5 6.7021859 10.545881 14.667437 10.5 15.53125 C 10.5 15.53125 4.6361997 15.5 4.53125 15.5 C 3.411786 15.5 2.5 16.361113 2.5 17.53125 C 2.5 18.695398 3.4117862 19.5 4.53125 19.5 L 11.28125 19.5 C 13.670662 19.5 14.5625 18.371672 14.5625 16.75 C 14.5625 16.297814 14.447357 7.3491532 14.5 6.5 C 14.5 6.5 20.212667 6.5 20.5625 6.5 C 21.681965 6.5 22.625 5.6038186 22.625 4.4375 C 22.625 3.6078835 21.681963 2.5 20.5625 2.5 L 13.59375 2.5 z " - xlink:href="#rect3167" - style="opacity:0.5;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999964;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="path3189" - inkscape:href="#rect3167" - d="M 13.59375,3.5 C 13.030939,3.5 12.555105,3.6824271 12.1875,4.0625 C 11.819895,4.4425729 11.5,5.0773217 11.5,6.25 C 11.5,6.4422606 11.52551,8.5611209 11.53125,10.71875 C 11.53699,12.876379 11.532515,14.981588 11.5,15.59375 C 11.466751,16.121392 11.028688,16.532076 10.5,16.53125 C 10.5,16.53125 9.0415375,16.539062 7.5625,16.53125 C 6.0834625,16.523438 4.4844395,16.5 4.53125,16.5 C 3.9247614,16.5 3.5,16.880753 3.5,17.53125 C 3.5,18.173084 3.8910974,18.5 4.53125,18.5 L 11.28125,18.5 C 12.318499,18.5 12.844693,18.260508 13.125,18 C 13.405307,17.739492 13.5625,17.377461 13.5625,16.75 C 13.5625,16.608813 13.522223,14.183039 13.5,11.78125 C 13.488888,10.580356 13.503404,9.3752554 13.5,8.40625 C 13.496596,7.4372446 13.478732,6.7805618 13.5,6.4375 C 13.533249,5.9098578 13.971312,5.4991739 14.5,5.5 C 14.5,5.5 20.212667,5.5 20.5625,5.5 C 21.148099,5.5 21.625,5.0646096 21.625,4.4375 C 21.625,4.4017167 21.537161,4.1026393 21.3125,3.875 C 21.087839,3.6473607 20.792241,3.5 20.5625,3.5 L 13.59375,3.5 z " /> - <image - id="image1322" - height="58.310913" - width="58.310913" - sodipodi:absref="/home/hbons/Desktop/Tango-Palette.png" - xlink:href="/home/hbons/Desktop/Tango-Palette.png" - x="-67.310913" - y="-20.310913" /> - </g> -</svg> diff --git a/libpurple/protocols/silc/resources/icons/48x48/apps/im-silc.png b/libpurple/protocols/silc/resources/icons/48x48/apps/im-silc.png Binary files differdeleted file mode 100644 index e43d9c2cb7..0000000000 --- a/libpurple/protocols/silc/resources/icons/48x48/apps/im-silc.png +++ /dev/null diff --git a/libpurple/protocols/silc/resources/icons/scalable/apps/im-silc.svg b/libpurple/protocols/silc/resources/icons/scalable/apps/im-silc.svg deleted file mode 100644 index aa3dad08d3..0000000000 --- a/libpurple/protocols/silc/resources/icons/scalable/apps/im-silc.svg +++ /dev/null @@ -1,153 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:xlink="http://www.w3.org/1999/xlink" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="48" - height="48" - id="svg2" - sodipodi:version="0.32" - inkscape:version="0.46" - version="1.0" - sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols/48" - sodipodi:docname="silc.svg" - inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/silc.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90" - inkscape:output_extension="org.inkscape.output.svg.inkscape"> - <defs - id="defs4"> - <linearGradient - inkscape:collect="always" - id="linearGradient2193"> - <stop - style="stop-color:#ffffff;stop-opacity:1;" - offset="0" - id="stop2195" /> - <stop - style="stop-color:#ffffff;stop-opacity:0;" - offset="1" - id="stop2197" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient2222"> - <stop - style="stop-color:#8ae234;stop-opacity:1;" - offset="0" - id="stop2224" /> - <stop - style="stop-color:#8ae234;stop-opacity:0;" - offset="1" - id="stop2226" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient3150"> - <stop - style="stop-color:#2e3436;stop-opacity:1;" - offset="0" - id="stop3152" /> - <stop - style="stop-color:#2e3436;stop-opacity:0;" - offset="1" - id="stop3154" /> - </linearGradient> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient3150" - id="radialGradient3156" - cx="10.748654" - cy="10.457643" - fx="10.748654" - fy="10.457643" - r="6.6449099" - gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)" - gradientUnits="userSpaceOnUse" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient2222" - id="linearGradient1318" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(2.08567,0,0,1.999113,-1.709138,-1.492105)" - x1="14.315197" - y1="11.002394" - x2="13.638538" - y2="-28.749279" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient2193" - id="linearGradient2203" - x1="20.834801" - y1="17.936523" - x2="26.154163" - y2="21.007658" - gradientUnits="userSpaceOnUse" /> - </defs> - <sodipodi:namedview - id="base" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageopacity="0.0" - inkscape:pageshadow="2" - inkscape:zoom="13.788817" - inkscape:cx="35.001851" - inkscape:cy="20.952874" - inkscape:document-units="px" - inkscape:current-layer="layer1" - showgrid="true" - fill="#9db029" - showguides="true" - inkscape:guide-bbox="true" - inkscape:window-width="1268" - inkscape:window-height="971" - inkscape:window-x="6" - inkscape:window-y="21" /> - <metadata - id="metadata7"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - </cc:Work> - </rdf:RDF> - </metadata> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1"> - <path - sodipodi:type="arc" - style="opacity:0.35;fill:url(#radialGradient3156);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="path3140" - sodipodi:cx="10.748654" - sodipodi:cy="10.457643" - sodipodi:rx="6.6449099" - sodipodi:ry="2.3675451" - d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1 4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1 17.393564 10.457643 z" - transform="matrix(3.461296,0,0,2.111892,-13.20427,14.91459)" /> - <path - style="opacity:1;fill:url(#linearGradient1318);fill-opacity:1;stroke:#4e9a06;stroke-width:0.99999911;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="M 20.489949,11.011929 C 20.489949,11.915899 20.607326,27.829773 20.511631,29.556634 C 20.511631,29.556634 7.9604471,29.494161 7.7415566,29.494161 C 5.406724,29.494161 3.5050383,31.205765 3.5050383,33.545004 C 3.5050383,35.87227 5.406724,37.500189 7.7415566,37.500189 L 21.797683,37.500189 C 26.78121,37.500189 28.663439,35.244533 28.663439,32.002624 C 28.663439,31.098653 28.395875,13.209261 28.505671,11.511706 C 28.505671,11.511706 40.472455,11.511706 41.202093,11.511706 C 43.536926,11.511706 45.50004,9.6968193 45.50004,7.3652154 C 45.50004,5.7067176 43.536923,3.5056793 41.202093,3.5056793 L 26.642947,3.5056793 C 23.379817,3.5056793 20.489949,5.5738454 20.489949,11.011929 z " - id="rect3167" - sodipodi:nodetypes="ccssscscssscs" /> - <path - sodipodi:type="inkscape:offset" - inkscape:radius="-1.0564219" - inkscape:original="M 26.65625 3.5 C 23.393121 3.4999999 20.5 5.5619164 20.5 11 C 20.500001 11.90397 20.595695 27.835639 20.5 29.5625 C 20.5 29.562499 7.9688905 29.5 7.75 29.5 C 5.4151674 29.499999 3.5 31.192011 3.5 33.53125 C 3.5 35.858514 5.4151674 37.5 7.75 37.5 L 21.8125 37.5 C 26.796026 37.499998 28.65625 35.241909 28.65625 32 C 28.65625 31.096028 28.390204 13.197555 28.5 11.5 C 28.5 11.5 40.457862 11.5 41.1875 11.5 C 43.522335 11.5 45.5 9.7066039 45.5 7.375 C 45.500002 5.7165023 43.52233 3.5 41.1875 3.5 L 26.65625 3.5 z " - xlink:href="#rect3167" - style="opacity:0.5;fill:url(#linearGradient2203);fill-opacity:1.0;stroke:#ffffff;stroke-width:0.99999964;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="path1316" - inkscape:href="#rect3167" - d="M 26.65625,4.53125 C 25.249537,4.53125 24.032886,4.9412683 23.125,5.90625 C 22.217114,6.8712317 21.5625,8.4647612 21.5625,11 C 21.5625,11.415298 21.581781,15.655374 21.59375,19.96875 C 21.605719,24.282126 21.621325,28.562355 21.5625,29.625 C 21.532315,30.188634 21.064428,30.628998 20.5,30.625 C 20.5,30.625 17.347604,30.609375 14.1875,30.59375 C 11.027396,30.578125 7.758935,30.5625 7.75,30.5625 C 5.9336242,30.562499 4.5625,31.79623 4.5625,33.5625 C 4.5625,35.313821 5.8995405,36.4375 7.75,36.4375 L 21.78125,36.4375 C 24.114194,36.4375 25.537737,35.928156 26.375,35.1875 C 27.212263,34.446844 27.59375,33.417796 27.59375,32 C 27.59375,31.65099 27.521563,26.864091 27.46875,22.0625 C 27.442343,19.661704 27.415771,17.24736 27.40625,15.3125 C 27.396729,13.37764 27.400585,12.008829 27.4375,11.4375 C 27.467685,10.873866 27.935572,10.433502 28.5,10.4375 C 28.5,10.4375 40.457735,10.4375 41.1875,10.4375 C 42.9733,10.4375 44.4375,9.0816356 44.4375,7.34375 C 44.4375,6.9328186 44.123387,6.1347887 43.5,5.53125 C 42.876613,4.9277113 42.021185,4.53125 41.1875,4.53125 L 26.65625,4.53125 z " /> - </g> -</svg> diff --git a/libpurple/protocols/silc/resources/silc.gresource.xml b/libpurple/protocols/silc/resources/silc.gresource.xml deleted file mode 100644 index c92fc3b7c1..0000000000 --- a/libpurple/protocols/silc/resources/silc.gresource.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<gresources> - <gresource prefix="/im/pidgin/libpurple/silc"> - <file>icons/16x16/apps/im-silc.png</file> - <file>icons/16x16/apps/scalable/im-silc.svg</file> - <file>icons/22x22/apps/im-silc.png</file> - <file>icons/22x22/apps/scalable/im-silc.svg</file> - <file>icons/48x48/apps/im-silc.png</file> - <file>icons/scalable/apps/im-silc.svg</file> - </gresource> -</gresources> diff --git a/libpurple/protocols/silc/silc.c b/libpurple/protocols/silc/silc.c deleted file mode 100644 index 1dc26446a4..0000000000 --- a/libpurple/protocols/silc/silc.c +++ /dev/null @@ -1,2583 +0,0 @@ -/* - - silcpurple.c - - Author: Pekka Riikonen <priikone@silcnet.org> - - Copyright (C) 2004 - 2007 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. - -*/ - -#include <glib/gi18n-lib.h> -#include <glib/gstdio.h> - -#include <gplugin.h> -#include <gplugin-native.h> - -#include "silcpurple.h" -#include "ft.h" -#include "wb.h" - -struct _SilcProtocol { - PurpleProtocol parent; -}; - -extern SilcClientOperations ops; - -static PurpleProtocol *my_protocol = NULL; -static GSList *cmds = NULL; - -/* Error log message callback */ - -static SilcBool silcpurple_log_error(SilcLogType type, char *message, - void *context) -{ - silc_say(NULL, NULL, SILC_CLIENT_MESSAGE_ERROR, message); - return TRUE; -} - -static void -silcpurple_free(SilcPurple sg) -{ - g_return_if_fail(sg != NULL); - - g_cancellable_cancel(sg->cancellable); - g_clear_object(&sg->cancellable); - g_clear_object(&sg->sockconn); - - g_clear_pointer(&sg->client, silc_client_free); - g_clear_pointer(&sg->sha1hash, silc_hash_free); - g_clear_pointer(&sg->mimeass, silc_mime_assembler_free); - - g_clear_pointer(&sg->public_key, silc_pkcs_public_key_free); - g_clear_pointer(&sg->private_key, silc_pkcs_private_key_free); - - silc_free(sg); -} - -static GList * -silcpurple_away_states(G_GNUC_UNUSED PurpleProtocol *protocol, - PurpleAccount *account) -{ - PurpleStatusType *type; - GList *types = NULL; - - type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_AVAILABLE, NULL, TRUE, TRUE, FALSE); - types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_HYPER, _("Hyper Active"), TRUE, TRUE, FALSE); - types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_AWAY, NULL, TRUE, TRUE, FALSE); - types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, SILCPURPLE_STATUS_ID_BUSY, _("Busy"), TRUE, TRUE, FALSE); - types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_INDISPOSED, _("Indisposed"), TRUE, TRUE, FALSE); - types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_PAGE, _("Wake Me Up"), TRUE, TRUE, FALSE); - types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, SILCPURPLE_STATUS_ID_OFFLINE, NULL, TRUE, TRUE, FALSE); - types = g_list_append(types, type); - - return types; -} - -static void -silcpurple_set_status(PurpleProtocolServer *protocol_server, PurpleAccount *account, PurpleStatus *status) -{ - PurpleConnection *gc = purple_account_get_connection(account); - SilcPurple sg = NULL; - SilcUInt32 mode; - SilcBuffer idp; - unsigned char mb[4]; - const char *state; - - if (gc != NULL) - sg = purple_connection_get_protocol_data(gc); - - if (status == NULL) - return; - - state = purple_status_get_id(status); - - if (state == NULL) - return; - - if ((sg == NULL) || (sg->conn == NULL)) - return; - - mode = sg->conn->local_entry->mode; - mode &= ~(SILC_UMODE_GONE | - SILC_UMODE_HYPER | - SILC_UMODE_BUSY | - SILC_UMODE_INDISPOSED | - SILC_UMODE_PAGE); - - if (purple_strequal(state, "hyper")) - mode |= SILC_UMODE_HYPER; - else if (purple_strequal(state, "away")) - mode |= SILC_UMODE_GONE; - else if (purple_strequal(state, "busy")) - mode |= SILC_UMODE_BUSY; - else if (purple_strequal(state, "indisposed")) - mode |= SILC_UMODE_INDISPOSED; - else if (purple_strequal(state, "page")) - mode |= SILC_UMODE_PAGE; - - /* Send UMODE */ - idp = silc_id_payload_encode(sg->conn->local_id, SILC_ID_CLIENT); - SILC_PUT32_MSB(mode, mb); - silc_client_command_send(sg->client, sg->conn, SILC_COMMAND_UMODE, - silcpurple_command_reply, NULL, 2, - 1, idp->data, silc_buffer_len(idp), - 2, mb, sizeof(mb)); - silc_buffer_free(idp); -} - - -/*************************** Connection Routines *****************************/ - -static void -silcpurple_keepalive(PurpleProtocolServer *protocol_server, PurpleConnection *gc) -{ - SilcPurple sg = purple_connection_get_protocol_data(gc); - silc_packet_send(sg->conn->stream, SILC_PACKET_HEARTBEAT, 0, - NULL, 0); -} - -typedef struct { - SilcPurple sg; - SilcUInt32 fd; - guint tag; -} *SilcPurpleTask; - -/* A timeout occurred. Call SILC scheduler. */ - -static gboolean -silcpurple_scheduler_timeout(gpointer context) -{ - SilcPurpleTask task = (SilcPurpleTask)context; - silc_client_run_one(task->sg->client); - silc_dlist_del(task->sg->tasks, task); - silc_free(task); - return FALSE; -} - -/* An fd task event occurred. Call SILC scheduler. */ - -static void -silcpurple_scheduler_fd(gpointer data, gint fd, PurpleInputCondition cond) -{ - SilcClient client = (SilcClient)data; - silc_client_run_one(client); -} - -/* SILC Scheduler notify callback. This is called whenever task is added to - or deleted from SILC scheduler. It's also called when fd task events - change. Here we add same tasks to glib's main loop. */ - -static void -silcpurple_scheduler(SilcSchedule schedule, - SilcBool added, SilcTask task, - SilcBool fd_task, SilcUInt32 fd, - SilcTaskEvent event, - long seconds, long useconds, - void *context) -{ - SilcClient client = (SilcClient)context; - PurpleConnection *gc = client->application; - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcPurpleTask ptask = NULL; - - if (added) { - if (fd_task) { - /* Add fd or change fd events */ - PurpleInputCondition e = 0; - - silc_dlist_start(sg->tasks); - while ((ptask = silc_dlist_get(sg->tasks))) - if (ptask->fd == fd) { - g_source_remove(ptask->tag); - break; - } - - if (event & SILC_TASK_READ) - e |= PURPLE_INPUT_READ; - if (event & SILC_TASK_WRITE) - e |= PURPLE_INPUT_WRITE; - - if (e) { - if (!ptask) { - ptask = silc_calloc(1, sizeof(*ptask)); - ptask->fd = fd; - silc_dlist_add(sg->tasks, ptask); - } - ptask->tag = purple_input_add(fd, e, silcpurple_scheduler_fd, - client); - } else if (ptask) { - silc_dlist_del(sg->tasks, ptask); - silc_free(ptask); - } - } else { - /* Add timeout */ - ptask = silc_calloc(1, sizeof(*ptask)); - ptask->sg = sg; - ptask->tag = g_timeout_add((seconds * 1000) + - (useconds / 1000), - silcpurple_scheduler_timeout, - ptask); - silc_dlist_add(sg->tasks, ptask); - } - } else { - if (fd_task) { - /* Remove fd */ - silc_dlist_start(sg->tasks); - while ((ptask = silc_dlist_get(sg->tasks))) - if (ptask->fd == fd) { - g_source_remove(ptask->tag); - silc_dlist_del(sg->tasks, ptask); - silc_free(ptask); - break; - } - } - } -} - -static void -silcpurple_connect_cb(SilcClient client, SilcClientConnection conn, - SilcClientConnectionStatus status, SilcStatus error, - const char *message, void *context) -{ - PurpleConnection *gc = context; - SilcPurple sg; - SilcUInt32 mask; - char tz[16]; - PurpleImage *img; -#ifdef HAVE_SYS_UTSNAME_H - struct utsname u; -#endif - - sg = purple_connection_get_protocol_data(gc); - - switch (status) { - case SILC_CLIENT_CONN_SUCCESS: - case SILC_CLIENT_CONN_SUCCESS_RESUME: - sg->conn = conn; - - /* Connection created successfully */ - purple_connection_set_state(gc, PURPLE_CONNECTION_STATE_CONNECTED); - - /* Send the server our buddy list */ - silcpurple_send_buddylist(gc); - - g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); - - /* Send any UMODEs configured for account */ - if (purple_account_get_bool(sg->account, "block-ims", FALSE)) { - silc_client_command_call(sg->client, sg->conn, NULL, - "UMODE", "+P", NULL); - } - - /* Set default attributes */ - mask = SILC_ATTRIBUTE_MOOD_NORMAL; - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_STATUS_MOOD, - SILC_32_TO_PTR(mask), - sizeof(SilcUInt32)); - mask = SILC_ATTRIBUTE_CONTACT_CHAT; - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_PREFERRED_CONTACT, - SILC_32_TO_PTR(mask), - sizeof(SilcUInt32)); -#ifdef HAVE_SYS_UTSNAME_H - if (!uname(&u)) { - SilcAttributeObjDevice dev; - memset(&dev, 0, sizeof(dev)); - dev.type = SILC_ATTRIBUTE_DEVICE_COMPUTER; - dev.version = u.release; - dev.model = u.sysname; - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_DEVICE_INFO, - (void *)&dev, sizeof(dev)); - } -#endif - silc_timezone(tz, sizeof(tz)); - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_TIMEZONE, - (void *)tz, strlen(tz)); - - /* Set our buddy icon */ - img = purple_buddy_icons_find_account_icon(sg->account); - silcpurple_buddy_set_icon(NULL, gc, img); - g_object_unref(img); - - return; - break; - - case SILC_CLIENT_CONN_DISCONNECTED: - /* Disconnected */ - if (sg->resuming && !sg->detaching) - g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); - - /* Close the connection */ - if (!sg->detaching) - purple_connection_error(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Disconnected by server")); - else - /* TODO: Does this work correctly? Maybe we need to set wants_to_die? */ - purple_account_disconnect(purple_connection_get_account(gc)); - break; - - case SILC_CLIENT_CONN_ERROR: - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Error connecting to SILC Server")); - g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); - break; - - case SILC_CLIENT_CONN_ERROR_KE: - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, - _("Key Exchange failed")); - break; - - case SILC_CLIENT_CONN_ERROR_AUTH: - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, - _("Authentication failed")); - break; - - case SILC_CLIENT_CONN_ERROR_RESUME: - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, - _("Resuming detached session failed. " - "Press Reconnect to create new connection.")); - g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); - break; - - case SILC_CLIENT_CONN_ERROR_TIMEOUT: - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Connection timed out")); - break; - } - - /* Error */ - sg->conn = NULL; -} - -static void -silcpurple_stream_created(SilcSocketStreamStatus status, SilcStream stream, - void *context) -{ - PurpleConnection *gc = context; - SilcPurple sg; - SilcClient client; - SilcClientConnectionParams params; - const char *dfile; - - sg = purple_connection_get_protocol_data(gc); - - if (status != SILC_SOCKET_OK) { - purple_connection_error(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Connection failed")); - silcpurple_free(sg); - purple_connection_set_protocol_data(gc, NULL); - return; - } - - client = sg->client; - - /* Get session detachment data, if available */ - memset(¶ms, 0, sizeof(params)); - dfile = silcpurple_session_file(purple_account_get_username(sg->account)); - params.detach_data = (unsigned char *)silc_file_readfile(dfile, ¶ms.detach_data_len); - if (params.detach_data) - params.detach_data[params.detach_data_len] = 0; - params.ignore_requested_attributes = FALSE; - params.pfs = purple_account_get_bool(sg->account, "pfs", FALSE); - - /* Progress */ - if (params.detach_data) { - sg->resuming = TRUE; - } - - /* Perform SILC Key Exchange. */ - silc_client_key_exchange(client, ¶ms, sg->public_key, - sg->private_key, stream, SILC_CONN_SERVER, - silcpurple_connect_cb, gc); - - silc_free(params.detach_data); -} - -static void -silcpurple_login_connected(GObject *source, GAsyncResult *res, gpointer data) -{ - PurpleConnection *gc = data; - SilcPurple sg; - GSocketConnection *conn; - GSocket *socket; - gint fd; - GError *error = NULL; - - g_return_if_fail(gc != NULL); - - sg = purple_connection_get_protocol_data(gc); - - conn = g_socket_client_connect_to_host_finish(G_SOCKET_CLIENT(source), - res, &error); - if (conn == NULL) { - if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Connection failed")); - silcpurple_free(sg); - purple_connection_set_protocol_data(gc, NULL); - } - - g_clear_error(&error); - return; - } - - socket = g_socket_connection_get_socket(conn); - g_assert(socket != NULL); - - fd = g_socket_get_fd(socket); - sg->sockconn = conn; - - silc_hash_alloc((unsigned char *)"sha1", &sg->sha1hash); - - /* Wrap socket to TCP stream */ - silc_socket_tcp_stream_create(fd, TRUE, FALSE, - sg->client->schedule, - silcpurple_stream_created, gc); -} - -static void silcpurple_continue_running(SilcPurple sg) -{ - PurpleConnection *gc = sg->gc; - PurpleAccount *account = purple_connection_get_account(gc); - GSocketClient *client; - GError *error = NULL; - - client = purple_gio_socket_client_new(account, &error); - if (client == NULL) { - /* Assume it's a proxy error */ - purple_notify_error(NULL, NULL, _("Invalid proxy settings"), - error->message, - purple_request_cpar_from_account(account)); - purple_connection_take_error(gc, error); - purple_connection_set_protocol_data(gc, NULL); - silcpurple_free(sg); - return; - } - - /* Connect to the SILC server */ - g_socket_client_connect_to_host_async(client, - purple_account_get_string(account, "server", - "silc.silcnet.org"), - purple_account_get_int(account, "port", 706), - sg->cancellable, silcpurple_login_connected, gc); - g_object_unref(client); -} - -static void silcpurple_got_password_cb(PurpleConnection *gc, PurpleRequestFields *fields) -{ - SilcPurple sg = purple_connection_get_protocol_data(gc); - PurpleAccount *account = purple_connection_get_account(gc); - char pkd[256], prd[256]; - const char *password; - gboolean remember; - PurpleCredentialManager *manager; - - /* TODO: the password prompt dialog doesn't get disposed if the account disconnects */ - PURPLE_ASSERT_CONNECTION_IS_VALID(gc); - - password = purple_request_fields_get_string(fields, "password"); - remember = purple_request_fields_get_bool(fields, "remember"); - - if (!password || !*password) - { - purple_notify_error(gc, NULL, - _("Password is required to sign on."), NULL, - purple_request_cpar_from_connection(gc)); - purple_connection_set_protocol_data(gc, NULL); - silcpurple_free(sg); - return; - } - - if (remember) - purple_account_set_remember_password(account, TRUE); - - manager = purple_credential_manager_get_default(); - purple_credential_manager_write_password_async(manager, account, password, - NULL, NULL, NULL); - - /* Load SILC key pair */ - g_snprintf(pkd, sizeof(pkd), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir()); - g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir()); - if (!silc_load_key_pair((char *)purple_account_get_string(account, "public-key", pkd), - (char *)purple_account_get_string(account, "private-key", prd), - password, - &sg->public_key, &sg->private_key)) { - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, - _("Unable to load SILC key pair")); - purple_connection_set_protocol_data(gc, NULL); - silcpurple_free(sg); - return; - } - silcpurple_continue_running(sg); -} - -static void silcpurple_no_password_cb(PurpleConnection *gc, PurpleRequestFields *fields) -{ - SilcPurple sg; - - /* TODO: the password prompt dialog doesn't get disposed if the account disconnects */ - PURPLE_ASSERT_CONNECTION_IS_VALID(gc); - - sg = purple_connection_get_protocol_data(gc); - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, - _("Unable to load SILC key pair")); - purple_connection_set_protocol_data(gc, NULL); - silcpurple_free(sg); -} - -static void silcpurple_running(SilcClient client, void *context) -{ - SilcPurple sg = context; - PurpleConnection *gc = sg->gc; - PurpleAccount *account = purple_connection_get_account(gc); - char pkd[256], prd[256]; - - - /* Load SILC key pair */ - g_snprintf(pkd, sizeof(pkd), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir()); - g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir()); - if (!silc_load_key_pair((char *)purple_account_get_string(account, "public-key", pkd), - (char *)purple_account_get_string(account, "private-key", prd), - (purple_connection_get_password(gc) == NULL) ? "" : purple_connection_get_password(gc), - &sg->public_key, &sg->private_key)) { - if (!purple_connection_get_password(gc)) { - purple_account_request_password(account, G_CALLBACK(silcpurple_got_password_cb), - G_CALLBACK(silcpurple_no_password_cb), gc); - return; - } - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, - _("Unable to load SILC key pair")); - purple_connection_set_protocol_data(gc, NULL); - silcpurple_free(sg); - return; - } - silcpurple_continue_running(sg); -} - -static void -silcpurple_login(G_GNUC_UNUSED PurpleProtocol *protocol, - PurpleAccount *account) -{ - SilcClient client; - PurpleConnection *gc; - SilcPurple sg; - SilcClientParams params; - const char *cipher, *hmac; - char *username, *hostname, *realname, **up; - int i; - - gc = purple_account_get_connection(account); - if (!gc) - return; - - purple_connection_set_protocol_data(gc, NULL); - - memset(¶ms, 0, sizeof(params)); - strcat(params.nickname_format, "%n#a"); - - /* Allocate SILC client */ - client = silc_client_alloc(&ops, ¶ms, gc, NULL); - if (!client) { - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, - _("Out of memory")); - return; - } - - /* Get username, real name and local hostname for SILC library */ - if (!purple_account_get_username(account)) - purple_account_set_username(account, silc_get_username()); - - username = (char *)purple_account_get_username(account); - up = g_strsplit(username, "@", 2); - username = g_strdup(up[0]); - g_strfreev(up); - - if (!purple_account_get_user_info(account)) { - purple_account_set_user_info(account, silc_get_real_name()); - if (!purple_account_get_user_info(account)) - purple_account_set_user_info(account, - "John T. Noname"); - } - realname = (char *)purple_account_get_user_info(account); - hostname = silc_net_localhost(); - - purple_connection_set_display_name(gc, username); - - /* Register requested cipher and HMAC */ - cipher = purple_account_get_string(account, "cipher", - SILC_DEFAULT_CIPHER); - for (i = 0; silc_default_ciphers[i].name; i++) - if (purple_strequal(silc_default_ciphers[i].name, cipher)) { - silc_cipher_register(&(silc_default_ciphers[i])); - break; - } - hmac = purple_account_get_string(account, "hmac", SILC_DEFAULT_HMAC); - for (i = 0; silc_default_hmacs[i].name; i++) - if (purple_strequal(silc_default_hmacs[i].name, hmac)) { - silc_hmac_register(&(silc_default_hmacs[i])); - break; - } - - sg = silc_calloc(1, sizeof(*sg)); - if (!sg) - return; - sg->cancellable = g_cancellable_new(); - sg->client = client; - sg->gc = gc; - sg->account = account; - purple_connection_set_protocol_data(gc, sg); - - /* Init SILC client */ - if (!silc_client_init(client, username, hostname, realname, - silcpurple_running, sg)) { - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, - _("Unable to initialize SILC protocol")); - purple_connection_set_protocol_data(gc, NULL); - silcpurple_free(sg); - silc_free(hostname); - g_free(username); - return; - } - silc_free(hostname); - g_free(username); - - /* Check the ~/.silc dir and create it, and new key pair if necessary. */ - if (!silcpurple_check_silc_dir(gc)) { - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, - _("Error loading SILC key pair")); - purple_connection_set_protocol_data(gc, NULL); - silcpurple_free(sg); - return; - } - - /* Run SILC scheduler */ - sg->tasks = silc_dlist_init(); - silc_schedule_set_notify(client->schedule, silcpurple_scheduler, - client); - silc_client_run_one(client); -} - -static int -silcpurple_close_final(gpointer *context) -{ - SilcPurple sg = (SilcPurple)context; - - purple_debug_info("silc", "Finalizing SilcPurple %p\n", sg); - - silc_client_stop(sg->client, NULL, NULL); - - silcpurple_free(sg); - return 0; -} - -static gchar * -silcpurple_get_quit_message(void) -{ - PurpleUiInfo *ui_info; - const char *ui_name = NULL, *ui_website = NULL; - char *quit_msg; - - ui_info = purple_core_get_ui_info(); - if (PURPLE_IS_UI_INFO(ui_info)) { - ui_name = purple_ui_info_get_name(ui_info); - ui_website = purple_ui_info_get_website(ui_info); - } - - if (!ui_name || !ui_website) { - ui_name = "Pidgin"; - ui_website = PURPLE_WEBSITE; - } - - quit_msg = g_strdup_printf(_("Download %s: %s"), ui_name, ui_website); - - return quit_msg; -} - -static void -silcpurple_close(G_GNUC_UNUSED PurpleProtocol *protocol, PurpleConnection *gc) -{ - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcPurpleTask task; - char *quit_msg; - - g_return_if_fail(sg != NULL); - - quit_msg = silcpurple_get_quit_message(); - - /* Send QUIT */ - silc_client_command_call(sg->client, sg->conn, NULL, - "QUIT", quit_msg, NULL); - g_free(quit_msg); - - if (sg->conn) - silc_client_close_connection(sg->client, sg->conn); - - if (sg->conn) - silc_client_run_one(sg->client); - silc_schedule_set_notify(sg->client->schedule, NULL, NULL); - - silc_dlist_start(sg->tasks); - while ((task = silc_dlist_get(sg->tasks))) { - g_source_remove(task->tag); - silc_free(task); - } - silc_dlist_uninit(sg->tasks); - - if (sg->scheduler) - g_source_remove(sg->scheduler); - - purple_debug_info("silc", "Scheduling destruction of SilcPurple %p\n", sg); - g_timeout_add(1, (GSourceFunc)silcpurple_close_final, sg); -} - - -/****************************** Protocol Actions *****************************/ - -static void -silcpurple_attrs_cancel(PurpleConnection *gc, PurpleRequestFields *fields) -{ - /* Nothing */ -} - -static void -silcpurple_attrs_cb(PurpleConnection *gc, PurpleRequestFields *fields) -{ - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - PurpleRequestField *f; - char *tmp; - SilcUInt32 tmp_len, mask; - SilcAttributeObjService service; - SilcAttributeObjDevice dev; - SilcVCardStruct vcard; - const char *val; - - sg = purple_connection_get_protocol_data(gc); - if (!sg) - return; - - memset(&service, 0, sizeof(service)); - memset(&dev, 0, sizeof(dev)); - memset(&vcard, 0, sizeof(vcard)); - - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_USER_INFO, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_SERVICE, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_STATUS_MOOD, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_STATUS_FREETEXT, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_STATUS_MESSAGE, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_PREFERRED_LANGUAGE, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_PREFERRED_CONTACT, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_TIMEZONE, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_GEOLOCATION, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_DEVICE_INFO, NULL); - - /* Set mood */ - mask = 0; - f = purple_request_fields_get_field(fields, "mood_normal"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_NORMAL; - f = purple_request_fields_get_field(fields, "mood_happy"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_HAPPY; - f = purple_request_fields_get_field(fields, "mood_sad"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_SAD; - f = purple_request_fields_get_field(fields, "mood_angry"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_ANGRY; - f = purple_request_fields_get_field(fields, "mood_jealous"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_JEALOUS; - f = purple_request_fields_get_field(fields, "mood_ashamed"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_ASHAMED; - f = purple_request_fields_get_field(fields, "mood_invincible"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_INVINCIBLE; - f = purple_request_fields_get_field(fields, "mood_inlove"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_INLOVE; - f = purple_request_fields_get_field(fields, "mood_sleepy"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_SLEEPY; - f = purple_request_fields_get_field(fields, "mood_bored"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_BORED; - f = purple_request_fields_get_field(fields, "mood_excited"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_EXCITED; - f = purple_request_fields_get_field(fields, "mood_anxious"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_ANXIOUS; - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_STATUS_MOOD, - SILC_32_TO_PTR(mask), - sizeof(SilcUInt32)); - - /* Set preferred contact */ - mask = 0; - f = purple_request_fields_get_field(fields, "contact_chat"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_CONTACT_CHAT; - f = purple_request_fields_get_field(fields, "contact_email"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_CONTACT_EMAIL; - f = purple_request_fields_get_field(fields, "contact_call"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_CONTACT_CALL; - f = purple_request_fields_get_field(fields, "contact_sms"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_CONTACT_SMS; - f = purple_request_fields_get_field(fields, "contact_mms"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_CONTACT_MMS; - f = purple_request_fields_get_field(fields, "contact_video"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_CONTACT_VIDEO; - if (mask) - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_PREFERRED_CONTACT, - SILC_32_TO_PTR(mask), - sizeof(SilcUInt32)); - - /* Set status text */ - val = NULL; - f = purple_request_fields_get_field(fields, "status_text"); - if (f) - val = purple_request_field_string_get_value(f); - if (val && *val) - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_STATUS_FREETEXT, - (void *)val, strlen(val)); - - /* Set vcard */ - val = NULL; - f = purple_request_fields_get_field(fields, "vcard"); - if (f) - val = purple_request_field_string_get_value(f); - if (val && *val) { - purple_account_set_string(sg->account, "vcard", val); - tmp = silc_file_readfile(val, &tmp_len); - if (tmp) { - tmp[tmp_len] = 0; - if (silc_vcard_decode((unsigned char *)tmp, tmp_len, &vcard)) - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_USER_INFO, - (void *)&vcard, - sizeof(vcard)); - } - silc_vcard_free(&vcard); - silc_free(tmp); - } else { - purple_account_set_string(sg->account, "vcard", ""); - } - -#ifdef HAVE_SYS_UTSNAME_H - /* Set device info */ - f = purple_request_fields_get_field(fields, "device"); - if (f && purple_request_field_bool_get_value(f)) { - struct utsname u; - if (!uname(&u)) { - dev.type = SILC_ATTRIBUTE_DEVICE_COMPUTER; - dev.version = u.release; - dev.model = u.sysname; - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_DEVICE_INFO, - (void *)&dev, sizeof(dev)); - } - } -#endif - - /* Set timezone */ - val = NULL; - f = purple_request_fields_get_field(fields, "timezone"); - if (f) - val = purple_request_field_string_get_value(f); - if (val && *val) - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_TIMEZONE, - (void *)val, strlen(val)); -} - -static void -silcpurple_attrs(G_GNUC_UNUSED GSimpleAction *action, - GVariant *parameter, - G_GNUC_UNUSED gpointer data) -{ - const gchar *account_id = NULL; - PurpleAccountManager *manager = NULL; - PurpleAccount *account = NULL; - PurpleConnection *gc = NULL; - SilcPurple sg = NULL; - SilcClient client = NULL; - SilcClientConnection conn = NULL; - PurpleRequestFields *fields; - PurpleRequestFieldGroup *g; - PurpleRequestField *f; - SilcHashTable attrs; - SilcAttributePayload attr; - gboolean mnormal = TRUE, mhappy = FALSE, msad = FALSE, - mangry = FALSE, mjealous = FALSE, mashamed = FALSE, - minvincible = FALSE, minlove = FALSE, msleepy = FALSE, - mbored = FALSE, mexcited = FALSE, manxious = FALSE; - gboolean cemail = FALSE, ccall = FALSE, csms = FALSE, - cmms = FALSE, cchat = TRUE, cvideo = FALSE; -#ifdef HAVE_SYS_UTSNAME_H - gboolean device = TRUE; -#endif - char status[1024], tz[16]; - - if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) { - g_critical("SILC attrs action parameter is of incorrect type %s", - g_variant_get_type_string(parameter)); - } - - account_id = g_variant_get_string(parameter, NULL); - manager = purple_account_manager_get_default(); - account = purple_account_manager_find_by_id(manager, account_id); - gc = purple_account_get_connection(account); - - sg = purple_connection_get_protocol_data(gc); - if (!sg) - return; - - client = sg->client; - conn = sg->conn; - - memset(status, 0, sizeof(status)); - - attrs = silc_client_attributes_get(client, conn); - if (attrs) { - if (silc_hash_table_find(attrs, - SILC_32_TO_PTR(SILC_ATTRIBUTE_STATUS_MOOD), - NULL, (void *)&attr)) { - SilcUInt32 mood = 0; - silc_attribute_get_object(attr, &mood, sizeof(mood)); - mnormal = !mood; - mhappy = (mood & SILC_ATTRIBUTE_MOOD_HAPPY); - msad = (mood & SILC_ATTRIBUTE_MOOD_SAD); - mangry = (mood & SILC_ATTRIBUTE_MOOD_ANGRY); - mjealous = (mood & SILC_ATTRIBUTE_MOOD_JEALOUS); - mashamed = (mood & SILC_ATTRIBUTE_MOOD_ASHAMED); - minvincible = (mood & SILC_ATTRIBUTE_MOOD_INVINCIBLE); - minlove = (mood & SILC_ATTRIBUTE_MOOD_INLOVE); - msleepy = (mood & SILC_ATTRIBUTE_MOOD_SLEEPY); - mbored = (mood & SILC_ATTRIBUTE_MOOD_BORED); - mexcited = (mood & SILC_ATTRIBUTE_MOOD_EXCITED); - manxious = (mood & SILC_ATTRIBUTE_MOOD_ANXIOUS); - } - - if (silc_hash_table_find(attrs, - SILC_32_TO_PTR(SILC_ATTRIBUTE_PREFERRED_CONTACT), - NULL, (void *)&attr)) { - SilcUInt32 contact = 0; - silc_attribute_get_object(attr, &contact, sizeof(contact)); - cemail = (contact & SILC_ATTRIBUTE_CONTACT_EMAIL); - ccall = (contact & SILC_ATTRIBUTE_CONTACT_CALL); - csms = (contact & SILC_ATTRIBUTE_CONTACT_SMS); - cmms = (contact & SILC_ATTRIBUTE_CONTACT_MMS); - cchat = (contact & SILC_ATTRIBUTE_CONTACT_CHAT); - cvideo = (contact & SILC_ATTRIBUTE_CONTACT_VIDEO); - } - - if (silc_hash_table_find(attrs, - SILC_32_TO_PTR(SILC_ATTRIBUTE_STATUS_FREETEXT), - NULL, (void *)&attr)) - silc_attribute_get_object(attr, &status, sizeof(status)); - -#ifdef HAVE_SYS_UTSNAME_H - if (!silc_hash_table_find(attrs, - SILC_32_TO_PTR(SILC_ATTRIBUTE_DEVICE_INFO), - NULL, (void *)&attr)) - device = FALSE; -#endif - } - - fields = purple_request_fields_new(); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_label_new("l3", _("Your Current Mood")); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_normal", _("Normal"), mnormal); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_happy", _("Happy"), mhappy); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_sad", _("Sad"), msad); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_angry", _("Angry"), mangry); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_jealous", _("Jealous"), mjealous); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_ashamed", _("Ashamed"), mashamed); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_invincible", _("Invincible"), minvincible); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_inlove", _("In love"), minlove); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_sleepy", _("Sleepy"), msleepy); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_bored", _("Bored"), mbored); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_excited", _("Excited"), mexcited); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_anxious", _("Anxious"), manxious); - purple_request_field_group_add_field(g, f); - - f = purple_request_field_label_new("l4", _("\nYour Preferred Contact Methods")); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("contact_chat", _("Chat"), cchat); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("contact_email", _("Email"), cemail); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("contact_call", _("Phone"), ccall); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("contact_sms", _("SMS"), csms); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("contact_mms", _("MMS"), cmms); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("contact_video", _("Video conferencing"), cvideo); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_string_new("status_text", _("Your Current Status"), - status[0] ? status : NULL, TRUE); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - g = purple_request_field_group_new(NULL); -#ifdef HAVE_SYS_UTSNAME_H - f = purple_request_field_bool_new("device", - _("Let others see what computer you are using"), - device); - purple_request_field_group_add_field(g, f); -#endif - purple_request_fields_add_group(fields, g); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_string_new("vcard", _("Your VCard File"), - purple_account_get_string(sg->account, "vcard", ""), - FALSE); - purple_request_field_group_add_field(g, f); - - silc_timezone(tz, sizeof(tz)); - f = purple_request_field_string_new("timezone", _("Timezone (UTC)"), tz, FALSE); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - purple_request_fields(gc, _("User Online Status Attributes"), - _("User Online Status Attributes"), - _("You can let other users see your online status information " - "and your personal information. Please fill the information " - "you would like other users to see about yourself."), - fields, - _("OK"), G_CALLBACK(silcpurple_attrs_cb), - _("Cancel"), G_CALLBACK(silcpurple_attrs_cancel), - purple_request_cpar_from_connection(gc), gc); -} - -static void -silcpurple_detach(G_GNUC_UNUSED GSimpleAction *action, - GVariant *parameter, - G_GNUC_UNUSED gpointer data) -{ - const gchar *account_id = NULL; - PurpleAccountManager *manager = NULL; - PurpleAccount *account = NULL; - PurpleConnection *connection = NULL; - SilcPurple sg = NULL; - - if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) { - g_critical("SILC detach action parameter is of incorrect type %s", - g_variant_get_type_string(parameter)); - } - - account_id = g_variant_get_string(parameter, NULL); - manager = purple_account_manager_get_default(); - account = purple_account_manager_find_by_id(manager, account_id); - connection = purple_account_get_connection(account); - if (!connection) { - return; - } - - sg = purple_connection_get_protocol_data(connection); - if (!sg) { - return; - } - - /* Call DETACH */ - silc_client_command_call(sg->client, sg->conn, "DETACH"); - sg->detaching = TRUE; -} - -static void -silcpurple_view_motd(G_GNUC_UNUSED GSimpleAction *action, - GVariant *parameter, - G_GNUC_UNUSED gpointer data) -{ - const gchar *account_id = NULL; - PurpleAccountManager *manager = NULL; - PurpleAccount *account = NULL; - PurpleConnection *connection = NULL; - SilcPurple sg = NULL; - char *tmp; - - if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) { - g_critical("SILC view MOTD action parameter is of incorrect type %s", - g_variant_get_type_string(parameter)); - } - - account_id = g_variant_get_string(parameter, NULL); - manager = purple_account_manager_get_default(); - account = purple_account_manager_find_by_id(manager, account_id); - connection = purple_account_get_connection(account); - if (!connection) { - return; - } - - sg = purple_connection_get_protocol_data(connection); - if (!sg) { - return; - } - - if (!sg->motd) { - purple_notify_error(connection, _("Message of the Day"), _("No Message " - "of the Day available"), _("There is no Message of the " - "Day associated with this connection"), - purple_request_cpar_from_connection(connection)); - return; - } - - tmp = g_markup_escape_text(sg->motd, -1); - purple_notify_formatted(connection, NULL, _("Message of the Day"), NULL, - tmp, NULL, NULL); - g_free(tmp); -} - -static void -silcpurple_create_keypair_cancel(PurpleConnection *gc, PurpleRequestFields *fields) -{ - /* Nothing */ -} - -static void -silcpurple_create_keypair_cb(PurpleConnection *gc, PurpleRequestFields *fields) -{ - SilcPurple sg; - PurpleRequestField *f; - const char *val, *pkfile = NULL, *prfile = NULL; - const char *pass1 = NULL, *pass2 = NULL, *un = NULL, *hn = NULL; - const char *rn = NULL, *e = NULL, *o = NULL, *c = NULL; - char *identifier; - int keylen = SILCPURPLE_DEF_PKCS_LEN; - SilcPublicKey public_key; - - sg = purple_connection_get_protocol_data(gc); - if (!sg) - return; - - val = NULL; - f = purple_request_fields_get_field(fields, "pass1"); - if (f) - val = purple_request_field_string_get_value(f); - if (val && *val) - pass1 = val; - else - pass1 = ""; - val = NULL; - f = purple_request_fields_get_field(fields, "pass2"); - if (f) - val = purple_request_field_string_get_value(f); - if (val && *val) - pass2 = val; - else - pass2 = ""; - - if (!purple_strequal(pass1, pass2)) { - purple_notify_error(gc, _("Create New SILC Key Pair"), - _("Passphrases do not match"), NULL, - purple_request_cpar_from_connection(gc)); - return; - } - - val = NULL; - f = purple_request_fields_get_field(fields, "key"); - if (f) - val = purple_request_field_string_get_value(f); - if (val && *val) - keylen = atoi(val); - f = purple_request_fields_get_field(fields, "pkfile"); - if (f) - pkfile = purple_request_field_string_get_value(f); - f = purple_request_fields_get_field(fields, "prfile"); - if (f) - prfile = purple_request_field_string_get_value(f); - - f = purple_request_fields_get_field(fields, "un"); - if (f) - un = purple_request_field_string_get_value(f); - f = purple_request_fields_get_field(fields, "hn"); - if (f) - hn = purple_request_field_string_get_value(f); - f = purple_request_fields_get_field(fields, "rn"); - if (f) - rn = purple_request_field_string_get_value(f); - f = purple_request_fields_get_field(fields, "e"); - if (f) - e = purple_request_field_string_get_value(f); - f = purple_request_fields_get_field(fields, "o"); - if (f) - o = purple_request_field_string_get_value(f); - f = purple_request_fields_get_field(fields, "c"); - if (f) - c = purple_request_field_string_get_value(f); - - identifier = silc_pkcs_silc_encode_identifier((char *)un, (char *)hn, - (char *)rn, (char *)e, - (char *)o, (char *)c, - NULL); - - /* Create the key pair */ - if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS, keylen, pkfile, prfile, - identifier, pass1, &public_key, NULL, - FALSE)) { - purple_notify_error(gc, _("Create New SILC Key Pair"), - _("Key Pair Generation failed"), NULL, - purple_request_cpar_from_connection(gc)); - return; - } - - silcpurple_show_public_key(sg, NULL, public_key, NULL, NULL); - - silc_pkcs_public_key_free(public_key); - silc_free(identifier); -} - -static void -silcpurple_create_keypair(G_GNUC_UNUSED GSimpleAction *action, - GVariant *parameter, - G_GNUC_UNUSED gpointer data) -{ - const gchar *account_id = NULL; - PurpleAccountManager *manager = NULL; - PurpleAccount *account = NULL; - PurpleConnection *connection = NULL; - PurpleRequestFields *fields; - PurpleRequestFieldGroup *g; - PurpleRequestField *f; - const char *username, *realname; - char *hostname, **u; - char tmp[256], pkd[256], pkd2[256], prd[256], prd2[256]; - - if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) { - g_critical("SILC create keypair action parameter is of incorrect type %s", - g_variant_get_type_string(parameter)); - } - - account_id = g_variant_get_string(parameter, NULL); - manager = purple_account_manager_get_default(); - account = purple_account_manager_find_by_id(manager, account_id); - connection = purple_account_get_connection(account); - - username = purple_account_get_username(account); - u = g_strsplit(username, "@", 2); - username = u[0]; - realname = purple_account_get_user_info(account); - hostname = silc_net_localhost(); - g_snprintf(tmp, sizeof(tmp), "%s@%s", username, hostname); - - g_snprintf(pkd2, sizeof(pkd2), "%s" G_DIR_SEPARATOR_S"public_key.pub", silcpurple_silcdir()); - g_snprintf(prd2, sizeof(prd2), "%s" G_DIR_SEPARATOR_S"private_key.prv", silcpurple_silcdir()); - g_snprintf(pkd, sizeof(pkd) - 1, "%s", - purple_account_get_string(account, "public-key", pkd2)); - g_snprintf(prd, sizeof(prd) - 1, "%s", - purple_account_get_string(account, "private-key", prd2)); - - fields = purple_request_fields_new(); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_string_new("key", _("Key length"), "2048", FALSE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("pkfile", _("Public key file"), pkd, FALSE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("prfile", _("Private key file"), prd, FALSE); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_string_new("un", _("Username"), username ? username : "", FALSE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("hn", _("Hostname"), hostname ? hostname : "", FALSE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("rn", _("Real name"), realname ? realname : "", FALSE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("e", _("Email"), tmp, FALSE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("o", _("Organization"), "", FALSE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("c", _("Country"), "", FALSE); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_string_new("pass1", _("Passphrase"), "", FALSE); - purple_request_field_string_set_masked(f, TRUE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("pass2", _("Passphrase (retype)"), "", FALSE); - purple_request_field_string_set_masked(f, TRUE); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - purple_request_fields(connection, _("Create New SILC Key Pair"), - _("Create New SILC Key Pair"), NULL, fields, - _("Generate Key Pair"), G_CALLBACK(silcpurple_create_keypair_cb), - _("Cancel"), G_CALLBACK(silcpurple_create_keypair_cancel), - purple_request_cpar_from_connection(connection), connection); - - g_strfreev(u); - silc_free(hostname); -} - -static void -silcpurple_change_pass(G_GNUC_UNUSED GSimpleAction *action, - GVariant *parameter, - G_GNUC_UNUSED gpointer data) -{ - const gchar *account_id = NULL; - PurpleAccountManager *manager = NULL; - PurpleAccount *account = NULL; - - if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) { - g_critical("SILC change password action parameter is of incorrect type %s", - g_variant_get_type_string(parameter)); - } - - account_id = g_variant_get_string(parameter, NULL); - manager = purple_account_manager_get_default(); - account = purple_account_manager_find_by_id(manager, account_id); - - purple_account_request_change_password(account); -} - -static void -silcpurple_change_passwd(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const char *old, const char *new) -{ - char prd[256]; - g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.pub", silcpurple_silcdir()); - silc_change_private_key_passphrase(purple_account_get_string(purple_connection_get_account(gc), - "private-key", - prd), old ? old : "", new ? new : ""); -} - -static void -silcpurple_show_set_info(G_GNUC_UNUSED GSimpleAction *action, - GVariant *parameter, - G_GNUC_UNUSED gpointer data) -{ - const gchar *account_id = NULL; - PurpleAccountManager *manager = NULL; - PurpleAccount *account = NULL; - - if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) { - g_critical("SILC change password action parameter is of incorrect type %s", - g_variant_get_type_string(parameter)); - } - - account_id = g_variant_get_string(parameter, NULL); - manager = purple_account_manager_get_default(); - account = purple_account_manager_find_by_id(manager, account_id); - - purple_account_request_change_user_info(account); -} - -static void -silcpurple_set_info(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const char *text) -{ -} - -static const gchar * -silcpurple_protocol_actions_get_prefix(PurpleProtocolActions *actions) { - return "prpl-silc"; -} - -static GActionGroup * -silcpurple_protocol_actions_get_action_group(PurpleProtocolActions *actions, - PurpleConnection *connection) -{ - GSimpleActionGroup *group = NULL; - GActionEntry entries[] = { - { - .name = "attrs", - .activate = silcpurple_attrs, - .parameter_type = "s", - }, - { - .name = "detach", - .activate = silcpurple_detach, - .parameter_type = "s", - }, - { - .name = "view-motd", - .activate = silcpurple_view_motd, - .parameter_type = "s", - }, - { - .name = "create-keypair", - .activate = silcpurple_create_keypair, - .parameter_type = "s", - }, - { - .name = "change-password", - .activate = silcpurple_change_pass, - .parameter_type = "s", - }, - { - .name = "set-user-info", - .activate = silcpurple_show_set_info, - .parameter_type = "s", - }, - }; - gsize nentries = G_N_ELEMENTS(entries); - - group = g_simple_action_group_new(); - g_action_map_add_action_entries(G_ACTION_MAP(group), entries, nentries, - connection); - - return G_ACTION_GROUP(group); -} - -static GMenu * -silcpurple_protocol_actions_get_menu(PurpleProtocolActions *actions) -{ - GMenu *menu = NULL; - GMenuItem *item = NULL; - - menu = g_menu_new(); - - item = g_menu_item_new(_("Online Status"), "prpl-silc.attrs"); - g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s", - "account"); - g_menu_append_item(menu, item); - g_object_unref(item); - - item = g_menu_item_new(_("Detach From Server"), "prpl-silc.detach"); - g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s", - "account"); - g_menu_append_item(menu, item); - g_object_unref(item); - - item = g_menu_item_new(_("View Message of the Day"), "prpl-silc.view-motd"); - g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s", - "account"); - g_menu_append_item(menu, item); - g_object_unref(item); - - item = g_menu_item_new(_("Create SILC Key Pair..."), - "prpl-silc.create-keypair"); - g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s", - "account"); - g_menu_append_item(menu, item); - g_object_unref(item); - - item = g_menu_item_new(_("Change Password..."), - "prpl-silc.change-password"); - g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s", - "account"); - g_menu_append_item(menu, item); - g_object_unref(item); - - item = g_menu_item_new(_("Set User Info..."), "prpl-silc.set-user-info"); - g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s", - "account"); - g_menu_append_item(menu, item); - g_object_unref(item); - - return menu; -} - - -/******************************* IM Routines *********************************/ - -typedef struct { - char *nick; - char *message; - SilcUInt32 message_len; - SilcMessageFlags flags; - PurpleMessageFlags gflags; -} *SilcPurpleIM; - -static void -silcpurple_send_im_resolved(SilcClient client, - SilcClientConnection conn, - SilcStatus status, - SilcDList clients, - void *context) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcPurpleIM im = context; - PurpleConversation *convo; - PurpleConversationManager *manager; - char tmp[256]; - SilcClientEntry client_entry; - SilcDList list; - gboolean free_list = FALSE; - const gchar *me; - PurpleMessage *msg; - - manager = purple_conversation_manager_get_default(); - convo = purple_conversation_manager_find_im(manager, sg->account, im->nick); - if (!convo) { - return; - } - - if (!clients) { - goto err; - } - - if (silc_dlist_count(clients) > 1) { - /* Find the correct one. The im->nick might be a formatted nick - so this will find the correct one. */ - clients = silc_client_get_clients_local(client, conn, - im->nick, FALSE); - if (!clients) - goto err; - - free_list = TRUE; - } - - silc_dlist_start(clients); - client_entry = silc_dlist_get(clients); - - me = purple_account_get_name_for_display(sg->account); - - /* Check for images */ - if (im->gflags & PURPLE_MESSAGE_IMAGES) { - list = silcpurple_image_message(im->message, &im->flags); - if (list) { - /* Send one or more MIME message. If more than one, they - are MIME fragments due to over large message */ - SilcBuffer buf; - - silc_dlist_start(list); - while ((buf = silc_dlist_get(list)) != SILC_LIST_END) - silc_client_send_private_message(client, conn, - client_entry, im->flags, sg->sha1hash, - buf->data, - silc_buffer_len(buf)); - silc_mime_partial_free(list); - msg = purple_message_new_outgoing(me, conn->local_entry->nickname, im->message, 0); - purple_conversation_write_message(convo, msg); - g_object_unref(G_OBJECT(msg)); - goto out; - } - } - - /* Send the message */ - silc_client_send_private_message(client, conn, client_entry, im->flags, - sg->sha1hash, (unsigned char *)im->message, im->message_len); - msg = purple_message_new_outgoing(me, conn->local_entry->nickname, im->message, 0); - purple_conversation_write_message(convo, msg); - g_object_unref(G_OBJECT(msg)); - goto out; - - err: - g_snprintf(tmp, sizeof(tmp), - _("User <I>%s</I> is not present in the network"), im->nick); - purple_conversation_write_system_message( - convo, tmp, 0); - - out: - if (free_list) { - silc_client_list_free(client, conn, clients); - } - g_free(im->nick); - g_free(im->message); - silc_free(im); -} - -static int -silcpurple_send_im(PurpleProtocolIM *pim, PurpleConnection *gc, - PurpleMessage *pmsg) -{ - SilcPurple sg = purple_connection_get_protocol_data(gc); - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcDList clients; - SilcClientEntry client_entry; - SilcMessageFlags mflags; - char *msg, *tmp; - int ret = 0; - gboolean sign = purple_account_get_bool(sg->account, "sign-verify", FALSE); - SilcDList list; - const gchar *rcpt = purple_message_get_recipient(pmsg); - const gchar *message = purple_message_get_contents(pmsg); - PurpleMessageFlags flags = purple_message_get_flags(pmsg); - - if (!rcpt || purple_message_is_empty(pmsg)) - return 0; - - mflags = SILC_MESSAGE_FLAG_UTF8; - - tmp = msg = purple_unescape_html(message); - - if (!g_ascii_strncasecmp(msg, "/me ", 4)) { - msg += 4; - if (!*msg) { - g_free(tmp); - return 0; - } - mflags |= SILC_MESSAGE_FLAG_ACTION; - } else if (strlen(msg) > 1 && msg[0] == '/') { - if (!silc_client_command_call(client, conn, msg + 1)) - purple_notify_error(gc, _("Call Command"), - _("Cannot call command"), - _("Unknown command"), - purple_request_cpar_from_connection(gc)); - g_free(tmp); - return 0; - } - - if (sign) - mflags |= SILC_MESSAGE_FLAG_SIGNED; - - /* Find client entry */ - clients = silc_client_get_clients_local(client, conn, rcpt, FALSE); - if (!clients) { - /* Resolve unknown user */ - SilcPurpleIM im = silc_calloc(1, sizeof(*im)); - if (!im) { - g_free(tmp); - return 0; - } - im->nick = g_strdup(rcpt); - im->message = g_strdup(message); - im->message_len = strlen(im->message); - im->flags = mflags; - im->gflags = flags; - silc_client_get_clients(client, conn, rcpt, NULL, - silcpurple_send_im_resolved, im); - g_free(tmp); - return 0; - } - silc_dlist_start(clients); - client_entry = silc_dlist_get(clients); - - /* Check for images */ - if (flags & PURPLE_MESSAGE_IMAGES) { - list = silcpurple_image_message(message, &mflags); - if (list) { - /* Send one or more MIME message. If more than one, they - are MIME fragments due to over large message */ - SilcBuffer buf; - - silc_dlist_start(list); - while ((buf = silc_dlist_get(list)) != SILC_LIST_END) - ret = - silc_client_send_private_message(client, conn, - client_entry, mflags, sg->sha1hash, - buf->data, - silc_buffer_len(buf)); - silc_mime_partial_free(list); - g_free(tmp); - silc_client_list_free(client, conn, clients); - return ret; - } - } - - /* Send private message directly */ - ret = silc_client_send_private_message(client, conn, client_entry, - mflags, sg->sha1hash, - (unsigned char *)msg, - strlen(msg)); - - g_free(tmp); - silc_client_list_free(client, conn, clients); - return ret; -} - - -static GList *silcpurple_blist_node_menu(PurpleProtocolClient *client, PurpleBlistNode *node) { - /* split this single menu building function back into the two - original: one for buddies and one for chats */ - if(PURPLE_IS_CHAT(node)) { - return silcpurple_chat_menu((PurpleChat *) node); - } else if(PURPLE_IS_BUDDY(node)) { - return silcpurple_buddy_menu((PurpleBuddy *) node); - } else { - g_return_val_if_reached(NULL); - } -} - -/********************************* Commands **********************************/ - -static PurpleCmdRet silcpurple_cmd_chat_part(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - PurpleConversation *chat = conv; - int id = 0; - - gc = purple_conversation_get_connection(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - if(args && args[0]) { - PurpleConversationManager *manager; - - manager = purple_conversation_manager_get_default(); - - chat = purple_conversation_manager_find_chat(manager, - purple_connection_get_account(gc), - args[0]); - } - - if (chat != NULL) - id = purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(chat)); - - if (id == 0) - return PURPLE_CMD_RET_FAILED; - - silcpurple_chat_leave(NULL, gc, id); - - return PURPLE_CMD_RET_OK; - -} - -static PurpleCmdRet silcpurple_cmd_chat_topic(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - int id = 0; - char *buf, *tmp, *tmp2; - const char *topic; - - gc = purple_conversation_get_connection(conv); - id = purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv)); - - if (gc == NULL || id == 0) - return PURPLE_CMD_RET_FAILED; - - if (!args || !args[0]) { - topic = purple_chat_conversation_get_topic(PURPLE_CHAT_CONVERSATION(conv)); - if (topic) { - tmp = g_markup_escape_text(topic, -1); - tmp2 = purple_markup_linkify(tmp); - buf = g_strdup_printf(_("current topic is: %s"), tmp2); - g_free(tmp); - g_free(tmp2); - } else - buf = g_strdup(_("No topic is set")); - purple_conversation_write_system_message(conv, - buf, PURPLE_MESSAGE_NO_LOG); - g_free(buf); - - } - - if (args && args[0] && (strlen(args[0]) > 255)) { - *error = g_strdup(_("Topic too long")); - return PURPLE_CMD_RET_FAILED; - } - - silcpurple_chat_set_topic(NULL, gc, id, args ? args[0] : NULL); - - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_chat_join(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - GHashTable *comp; - - if(!args || !args[0]) - return PURPLE_CMD_RET_FAILED; - - comp = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); - - g_hash_table_replace(comp, "channel", args[0]); - if(args[1]) - g_hash_table_replace(comp, "passphrase", args[1]); - - silcpurple_chat_join(NULL, purple_conversation_get_connection(conv), comp); - - g_hash_table_destroy(comp); - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_chat_list(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - gc = purple_conversation_get_connection(conv); - purple_roomlist_show_with_account(purple_connection_get_account(gc)); - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_whois(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - - gc = purple_conversation_get_connection(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - silcpurple_get_info(NULL, gc, args[0]); - - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_msg(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - int ret; - PurpleConnection *gc; - PurpleAccount *account; - const gchar *me; - PurpleMessage *msg; - - gc = purple_conversation_get_connection(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - account = purple_connection_get_account(gc); - me = purple_account_get_name_for_display(account); - msg = purple_message_new_outgoing(me, args[0], args[1], 0); - ret = silcpurple_send_im(NULL, gc, msg); - g_object_unref(G_OBJECT(msg)); - - if (ret) - return PURPLE_CMD_RET_OK; - else - return PURPLE_CMD_RET_FAILED; -} - -static PurpleCmdRet silcpurple_cmd_query(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - int ret = 1; - PurpleConversation *im; - PurpleConnection *gc; - PurpleAccount *account; - - if (!args || !args[0]) { - *error = g_strdup(_("You must specify a nick")); - return PURPLE_CMD_RET_FAILED; - } - - gc = purple_conversation_get_connection(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - account = purple_connection_get_account(gc); - - im = purple_im_conversation_new(account, args[0]); - - if (args[1]) { - const gchar *me = purple_account_get_name_for_display(account); - PurpleMessage *msg = purple_message_new_outgoing( - me, args[0], args[1], 0); - - ret = silcpurple_send_im(NULL, gc, msg); - purple_conversation_write_message(im, msg); - g_object_unref(G_OBJECT(msg)); - } - - if (ret) - return PURPLE_CMD_RET_OK; - else - return PURPLE_CMD_RET_FAILED; -} - -static PurpleCmdRet silcpurple_cmd_motd(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - SilcPurple sg; - char *tmp; - - gc = purple_conversation_get_connection(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = purple_connection_get_protocol_data(gc); - - if (sg == NULL) - return PURPLE_CMD_RET_FAILED; - - if (!sg->motd) { - *error = g_strdup(_("There is no Message of the Day associated with this connection")); - return PURPLE_CMD_RET_FAILED; - } - - tmp = g_markup_escape_text(sg->motd, -1); - purple_notify_formatted(gc, NULL, _("Message of the Day"), NULL, - tmp, NULL, NULL); - g_free(tmp); - - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_detach(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - SilcPurple sg; - - gc = purple_conversation_get_connection(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = purple_connection_get_protocol_data(gc); - - if (sg == NULL) - return PURPLE_CMD_RET_FAILED; - - silc_client_command_call(sg->client, sg->conn, "DETACH"); - sg->detaching = TRUE; - - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_cmode(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - SilcPurple sg; - SilcChannelEntry channel; - char *silccmd, *silcargs, *msg, tmp[256]; - const char *chname; - - gc = purple_conversation_get_connection(conv); - - if (gc == NULL || !args || purple_connection_get_protocol_data(gc) == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = purple_connection_get_protocol_data(gc); - - if (args[0]) - chname = args[0]; - else - chname = purple_conversation_get_name(conv); - - if (!args[1]) { - channel = silc_client_get_channel(sg->client, sg->conn, - (char *)chname); - if (!channel) { - *error = g_strdup_printf(_("channel %s not found"), chname); - return PURPLE_CMD_RET_FAILED; - } - if (channel->mode) { - silcpurple_get_chmode_string(channel->mode, tmp, sizeof(tmp)); - msg = g_strdup_printf(_("channel modes for %s: %s"), chname, tmp); - } else { - msg = g_strdup_printf(_("no channel modes are set on %s"), chname); - } - purple_conversation_write_system_message(conv, msg, PURPLE_MESSAGE_NO_LOG); - g_free(msg); - return PURPLE_CMD_RET_OK; - } - - silcargs = g_strjoinv(" ", args); - silccmd = g_strconcat(cmd, " ", silcargs, NULL); - g_free(silcargs); - if (!silc_client_command_call(sg->client, sg->conn, silccmd)) { - g_free(silccmd); - *error = g_strdup_printf(_("Failed to set cmodes for %s"), args[0]); - return PURPLE_CMD_RET_FAILED; - } - g_free(silccmd); - - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_generic(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - SilcPurple sg; - char *silccmd, *silcargs; - - gc = purple_conversation_get_connection(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = purple_connection_get_protocol_data(gc); - - if (sg == NULL) - return PURPLE_CMD_RET_FAILED; - - silcargs = g_strjoinv(" ", args); - silccmd = g_strconcat(cmd, " ", args ? silcargs : NULL, NULL); - g_free(silcargs); - if (!silc_client_command_call(sg->client, sg->conn, silccmd)) { - g_free(silccmd); - *error = g_strdup_printf(_("Unknown command: %s, (may be a client bug)"), cmd); - return PURPLE_CMD_RET_FAILED; - } - g_free(silccmd); - - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_quit(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - SilcPurple sg; - char *quit_msg; - - gc = purple_conversation_get_connection(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = purple_connection_get_protocol_data(gc); - - if (sg == NULL) - return PURPLE_CMD_RET_FAILED; - - if (args && args[0]) { - quit_msg = g_strdup(args[0]); - } else { - quit_msg = silcpurple_get_quit_message(); - } - - silc_client_command_call(sg->client, sg->conn, NULL, - "QUIT", quit_msg, NULL); - g_free(quit_msg); - - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_call(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - SilcPurple sg; - - gc = purple_conversation_get_connection(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = purple_connection_get_protocol_data(gc); - - if (sg == NULL) - return PURPLE_CMD_RET_FAILED; - - if (!silc_client_command_call(sg->client, sg->conn, args[0])) { - *error = g_strdup_printf(_("Unknown command: %s"), args[0]); - return PURPLE_CMD_RET_FAILED; - } - - return PURPLE_CMD_RET_OK; -} - - -/************************** Plugin Initialization ****************************/ - -static void -silcpurple_register_commands(void) -{ - PurpleCmdId id; - - id = purple_cmd_register("part", "w", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, - "prpl-silc", silcpurple_cmd_chat_part, _("part [channel]: Leave the chat"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("leave", "w", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, - "prpl-silc", silcpurple_cmd_chat_part, _("leave [channel]: Leave the chat"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("topic", "s", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", - silcpurple_cmd_chat_topic, _("topic [<new topic>]: View or change the topic"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("join", "ws", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, - "prpl-silc", silcpurple_cmd_chat_join, - _("join <channel> [<password>]: Join a chat on this network"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("list", "", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", - silcpurple_cmd_chat_list, _("list: List channels on this network"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("whois", "w", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, - "prpl-silc", - silcpurple_cmd_whois, _("whois <nick>: View nick's information"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("msg", "ws", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, - "prpl-silc", silcpurple_cmd_msg, - _("msg <nick> <message>: Send a private message to a user"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("query", "ws", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_query, - _("query <nick> [<message>]: Send a private message to a user"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("motd", "", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_motd, - _("motd: View the server's Message Of The Day"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("detach", "", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, - "prpl-silc", silcpurple_cmd_detach, - _("detach: Detach this session"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("quit", "s", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_quit, - _("quit [message]: Disconnect from the server, with an optional message"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("call", "s", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, - "prpl-silc", silcpurple_cmd_call, - _("call <command>: Call any silc client command"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - /* These below just get passed through for the silc client library to deal - * with */ - id = purple_cmd_register("kill", "ws", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("kill <nick> [-pubkey|<reason>]: Kill nick"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("nick", "w", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("nick <newnick>: Change your nickname"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("whowas", "ww", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("whowas <nick>: View nick's information"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("cmode", "wws", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_cmode, - _("cmode <channel> [+|-<modes>] [arguments]: Change or display channel modes"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("cumode", "wws", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("cumode <channel> +|-<modes> <nick>: Change nick's modes on channel"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("umode", "w", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("umode <usermodes>: Set your modes in the network"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("oper", "s", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("oper <nick> [-pubkey]: Get server operator privileges"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("invite", "ws", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("invite <channel> [-|+]<nick>: invite nick or add/remove from channel invite list"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("kick", "wws", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("kick <channel> <nick> [comment]: Kick client from channel"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("info", "w", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("info [server]: View server administrative details"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("ban", "ww", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("ban [<channel> +|-<nick>]: Ban client from channel"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("getkey", "w", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("getkey <nick|server>: Retrieve client's or server's public key"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("stats", "", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("stats: View server and network statistics"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("ping", "", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("ping: Send PING to the connected server"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); -} - -static void -silcpurple_unregister_commands(void) -{ - while (cmds) { - PurpleCmdId id = GPOINTER_TO_UINT(cmds->data); - purple_cmd_unregister(id); - cmds = g_slist_delete_link(cmds, cmds); - } -} - -static PurpleWhiteboardOps silcpurple_wb_ops = -{ - silcpurple_wb_start, - silcpurple_wb_end, - silcpurple_wb_get_dimensions, - silcpurple_wb_set_dimensions, - silcpurple_wb_get_brush, - silcpurple_wb_set_brush, - silcpurple_wb_send, - silcpurple_wb_clear, - - /* padding */ - { NULL, NULL, NULL, NULL } -}; - -static GList * -silcpurple_protocol_get_user_splits(G_GNUC_UNUSED PurpleProtocol *protocol) -{ - PurpleAccountUserSplit *split = purple_account_user_split_new(_("Network"), "silcnet.org", '@'); - - return g_list_append(NULL, split); -} - -static GList * -silcpurple_protocol_get_account_options(G_GNUC_UNUSED PurpleProtocol *protocol) -{ - PurpleAccountOption *option; - GList *account_options = NULL; - GList *list; - char tmp[256]; - - option = purple_account_option_string_new(_("Connect server"), "server", "silc.silcnet.org"); - account_options = g_list_append(account_options, option); - - option = purple_account_option_int_new(_("Port"), "port", 706); - account_options = g_list_append(account_options, option); - - g_snprintf(tmp, sizeof(tmp), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir()); - option = purple_account_option_string_new(_("Public Key file"), "public-key", tmp); - account_options = g_list_append(account_options, option); - - g_snprintf(tmp, sizeof(tmp), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir()); - option = purple_account_option_string_new(_("Private Key file"), "private-key", tmp); - account_options = g_list_append(account_options, option); - - list = NULL; - for (int i = 0; silc_default_ciphers[i].name; i++) { - PurpleKeyValuePair *kvp = purple_key_value_pair_new_full(silc_default_ciphers[i].name, - g_strdup(silc_default_ciphers[i].name), g_free); - list = g_list_append(list, kvp); - } - option = purple_account_option_list_new(_("Cipher"), "cipher", list); - account_options = g_list_append(account_options, option); - - list = NULL; - for (int i = 0; silc_default_hmacs[i].name; i++) { - PurpleKeyValuePair *kvp = purple_key_value_pair_new_full(silc_default_hmacs[i].name, - g_strdup(silc_default_hmacs[i].name), g_free); - list = g_list_append(list, kvp); - } - option = purple_account_option_list_new(_("HMAC"), "hmac", list); - account_options = g_list_append(account_options, option); - - option = purple_account_option_bool_new(_("Use Perfect Forward Secrecy"), "pfs", FALSE); - account_options = g_list_append(account_options, option); - - option = purple_account_option_bool_new(_("Public key authentication"), "pubkey-auth", FALSE); - account_options = g_list_append(account_options, option); - - option = purple_account_option_bool_new(_("Block IMs without Key Exchange"), "block-ims", FALSE); - account_options = g_list_append(account_options, option); - - option = purple_account_option_bool_new(_("Block messages to whiteboard"), "block-wb", FALSE); - account_options = g_list_append(account_options, option); - - option = purple_account_option_bool_new(_("Automatically open whiteboard"), "open-wb", FALSE); - account_options = g_list_append(account_options, option); - - option = purple_account_option_bool_new(_("Digitally sign and verify all messages"), "sign-verify", FALSE); - account_options = g_list_append(account_options, option); - - return account_options; -} - -static PurpleBuddyIconSpec * -silcpurple_protocol_get_buddy_icon_spec(G_GNUC_UNUSED PurpleProtocol *protocol) -{ - return purple_buddy_icon_spec_new("jpeg,gif,png,bmp", - 0, 0, 96, 96, 0, - PURPLE_ICON_SCALE_DISPLAY); -} - -static PurpleWhiteboardOps * -silcpurple_protocol_get_whiteboard_ops(G_GNUC_UNUSED PurpleProtocol *protocol) -{ - return &silcpurple_wb_ops; -} - -static void -silcpurple_protocol_init(G_GNUC_UNUSED SilcProtocol *self) -{ -} - -static void -silcpurple_protocol_class_init(SilcProtocolClass *klass) -{ - PurpleProtocolClass *protocol_class = PURPLE_PROTOCOL_CLASS(klass); - - protocol_class->login = silcpurple_login; - protocol_class->close = silcpurple_close; - protocol_class->status_types = silcpurple_away_states; - - protocol_class->get_user_splits = silcpurple_protocol_get_user_splits; - protocol_class->get_account_options = silcpurple_protocol_get_account_options; - protocol_class->get_buddy_icon_spec = silcpurple_protocol_get_buddy_icon_spec; - protocol_class->get_whiteboard_ops = silcpurple_protocol_get_whiteboard_ops; -} - -static void -silcpurple_protocol_class_finalize(G_GNUC_UNUSED SilcProtocolClass *klass) -{ -} - -static void -silcpurple_protocol_actions_iface_init(PurpleProtocolActionsInterface *iface) -{ - iface->get_prefix = silcpurple_protocol_actions_get_prefix; - iface->get_action_group = silcpurple_protocol_actions_get_action_group; - iface->get_menu = silcpurple_protocol_actions_get_menu; -} - -static void -silcpurple_protocol_client_iface_init(PurpleProtocolClientInterface *client_iface) -{ - client_iface->status_text = silcpurple_status_text; - client_iface->tooltip_text = silcpurple_tooltip_text; - client_iface->blist_node_menu = silcpurple_blist_node_menu; -} - -static void -silcpurple_protocol_server_iface_init(PurpleProtocolServerInterface *server_iface) -{ - server_iface->set_info = silcpurple_set_info; - server_iface->get_info = silcpurple_get_info; - server_iface->set_status = silcpurple_set_status; - server_iface->set_idle = silcpurple_idle_set; - server_iface->change_passwd = silcpurple_change_passwd; - server_iface->add_buddy = silcpurple_add_buddy; - server_iface->remove_buddy = silcpurple_remove_buddy; - server_iface->keepalive = silcpurple_keepalive; - server_iface->set_buddy_icon = silcpurple_buddy_set_icon; -} - -static void -silcpurple_protocol_im_iface_init(PurpleProtocolIMInterface *im_iface) -{ - im_iface->send = silcpurple_send_im; -} - -static void -silcpurple_protocol_chat_iface_init(PurpleProtocolChatInterface *chat_iface) -{ - chat_iface->info = silcpurple_chat_info; - chat_iface->info_defaults = silcpurple_chat_info_defaults; - chat_iface->join = silcpurple_chat_join; - chat_iface->get_name = silcpurple_get_chat_name; - chat_iface->invite = silcpurple_chat_invite; - chat_iface->leave = silcpurple_chat_leave; - chat_iface->send = silcpurple_chat_send; - chat_iface->set_topic = silcpurple_chat_set_topic; -} - -static void -silcpurple_protocol_roomlist_iface_init(PurpleProtocolRoomlistInterface *roomlist_iface) -{ - roomlist_iface->get_list = silcpurple_roomlist_get_list; - roomlist_iface->cancel = silcpurple_roomlist_cancel; -} - -static void -silcpurple_protocol_xfer_iface_init(PurpleProtocolXferInterface *xfer_iface) -{ - xfer_iface->send_file = silcpurple_ftp_send_file; - xfer_iface->new_xfer = silcpurple_ftp_new_xfer; -} - -G_DEFINE_DYNAMIC_TYPE_EXTENDED( - SilcProtocol, silcpurple_protocol, PURPLE_TYPE_PROTOCOL, 0, - - G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_ACTIONS, - silcpurple_protocol_actions_iface_init) - - G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_CLIENT, - silcpurple_protocol_client_iface_init) - - G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_SERVER, - silcpurple_protocol_server_iface_init) - - G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_IM, - silcpurple_protocol_im_iface_init) - - G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_CHAT, - silcpurple_protocol_chat_iface_init) - - G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_ROOMLIST, - silcpurple_protocol_roomlist_iface_init) - - G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_XFER, - silcpurple_protocol_xfer_iface_init)); - -static PurpleProtocol * -silcpurple_protocol_new(void) { - return PURPLE_PROTOCOL(g_object_new( - SILCPURPLE_TYPE_PROTOCOL, - "id", "prpl-silc", - "name", "SILC", - "description", _("Secure Internet Live Conferencing protocol."), - "icon-name", "im-silc", - "icon-resource-path", "/im/pidgin/libpurple/silc/icons", - "options", OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | - OPT_PROTO_PASSWORD_OPTIONAL | - OPT_PROTO_SLASH_COMMANDS_NATIVE, - NULL)); -} - -static GPluginPluginInfo * -silc_query(GError **error) -{ - const gchar * const authors[] = { - "Pekka Riikonen", - NULL - }; - - return purple_plugin_info_new( - "id", "prpl-silc", - "name", "SILC Protocol", - "version", "1.1", - "category", N_("Protocol"), - "summary", N_("SILC Protocol Plugin"), - "description", N_("Secure Internet Live Conferencing (SILC) Protocol"), - "authors", authors, - "website", "http://silcnet.org/", - "abi-version", PURPLE_ABI_VERSION, - "flags", PURPLE_PLUGIN_INFO_FLAGS_INTERNAL | - PURPLE_PLUGIN_INFO_FLAGS_AUTO_LOAD, - NULL - ); -} - -static gboolean -silc_load(GPluginPlugin *plugin, GError **error) -{ - PurpleProtocolManager *manager = purple_protocol_manager_get_default(); - - silcpurple_protocol_register_type(G_TYPE_MODULE(plugin)); - - silcpurple_xfer_register(G_TYPE_MODULE(plugin)); - - my_protocol = silcpurple_protocol_new(); - if(!purple_protocol_manager_register(manager, my_protocol, error)) { - g_clear_object(&my_protocol); - - return FALSE; - } - - purple_prefs_remove("/plugins/prpl/silc"); - - silc_log_set_callback(SILC_LOG_ERROR, silcpurple_log_error, NULL); - silcpurple_register_commands(); - - return TRUE; -} - -static gboolean -silc_unload(GPluginPlugin *plugin, gboolean shutdown, GError **error) -{ - PurpleProtocolManager *manager = purple_protocol_manager_get_default(); - - if(!purple_protocol_manager_unregister(manager, my_protocol, error)) { - return FALSE; - } - - silcpurple_unregister_commands(); - - g_clear_object(&my_protocol); - - return TRUE; -} - -GPLUGIN_NATIVE_PLUGIN_DECLARE(silc) diff --git a/libpurple/protocols/silc/silcpurple.h b/libpurple/protocols/silc/silcpurple.h deleted file mode 100644 index aebda61de0..0000000000 --- a/libpurple/protocols/silc/silcpurple.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - - silcpurple.h - - Author: Pekka Riikonen <priikone@silcnet.org> - - Copyright (C) 2004 - 2007 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 PURPLE_SILC_SILCPURPLE_H -#define PURPLE_SILC_SILCPURPLE_H - -#include <silc.h> -#include <silcclient.h> - -/* Purple includes */ -#include <purple.h> - -#define SILCPURPLE_TYPE_PROTOCOL (silcpurple_protocol_get_type()) -G_DECLARE_FINAL_TYPE(SilcProtocol, silcpurple_protocol, SILC, PROTOCOL, - PurpleProtocol) - -/* Default public and private key file names */ -#define SILCPURPLE_PUBLIC_KEY_NAME "public_key.pub" -#define SILCPURPLE_PRIVATE_KEY_NAME "private_key.prv" - -/* Default settings for creating key pair */ -#define SILCPURPLE_DEF_PKCS "rsa" -#define SILCPURPLE_DEF_PKCS_LEN 2048 - -#define SILCPURPLE_PRVGRP 0x001fffff - -/* Status IDs */ -#define SILCPURPLE_STATUS_ID_OFFLINE "offline" -#define SILCPURPLE_STATUS_ID_AVAILABLE "available" -#define SILCPURPLE_STATUS_ID_HYPER "hyper" -#define SILCPURPLE_STATUS_ID_AWAY "away" -#define SILCPURPLE_STATUS_ID_BUSY "busy" -#define SILCPURPLE_STATUS_ID_INDISPOSED "indisposed" -#define SILCPURPLE_STATUS_ID_PAGE "page" - -typedef struct { - unsigned long id; - const char *channel; - unsigned long chid; - const char *parentch; - SilcChannelPrivateKey key; -} *SilcPurplePrvgrp; - -/* The SILC Purple plugin context */ -typedef struct SilcPurpleStruct { - GCancellable *cancellable; - GSocketConnection *sockconn; - - SilcClient client; - SilcClientConnection conn; - SilcPublicKey public_key; - SilcPrivateKey private_key; - SilcHash sha1hash; - - SilcDList tasks; - guint scheduler; - PurpleConnection *gc; - PurpleAccount *account; - unsigned long channel_ids; - GList *grps; - - char *motd; - PurpleRoomlist *roomlist; - SilcMimeAssembler mimeass; - unsigned int detaching : 1; - unsigned int resuming : 1; - unsigned int roomlist_cancelled : 1; - unsigned int chpk : 1; -} *SilcPurple; - -void silc_say(SilcClient client, SilcClientConnection conn, - SilcClientMessageType type, char *msg, ...); -SilcBool silcpurple_command_reply(SilcClient client, SilcClientConnection conn, - SilcCommand command, SilcStatus status, - SilcStatus error, void *context, va_list ap); -gboolean silcpurple_check_silc_dir(PurpleConnection *gc); -const char *silcpurple_silcdir(void); -const char *silcpurple_session_file(const char *account); -void silcpurple_verify_public_key(SilcClient client, SilcClientConnection conn, - const char *name, - SilcConnectionType conn_type, - SilcPublicKey public_key, - SilcVerifyPublicKey completion, - void *context); -GList *silcpurple_buddy_menu(PurpleBuddy *buddy); -void silcpurple_add_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *message); -void silcpurple_send_buddylist(PurpleConnection *gc); -void silcpurple_remove_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group); -void silcpurple_buddy_keyagr_request(SilcClient client, - SilcClientConnection conn, - SilcClientEntry client_entry, - const char *hostname, SilcUInt16 port, - SilcUInt16 protocol); -void silcpurple_idle_set(PurpleProtocolServer *protocol_server, PurpleConnection *gc, int idle); -void silcpurple_tooltip_text(PurpleProtocolClient *ppclient, PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full); -char *silcpurple_status_text(PurpleProtocolClient *ppclient, PurpleBuddy *b); -gboolean silcpurple_ip_is_private(const char *ip); -void silcpurple_ftp_send_file(PurpleProtocolXfer *prplxfer, PurpleConnection *gc, const char *name, const char *file); -PurpleXfer *silcpurple_ftp_new_xfer(PurpleProtocolXfer *prplxfer, PurpleConnection *gc, const char *name); -void silcpurple_ftp_request(SilcClient client, SilcClientConnection conn, - SilcClientEntry client_entry, SilcUInt32 session_id, - const char *hostname, SilcUInt16 port); -void silcpurple_show_public_key(SilcPurple sg, - const char *name, SilcPublicKey public_key, - GCallback callback, void *context); -void silcpurple_get_info(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const char *who); -SilcAttributePayload -silcpurple_get_attr(SilcDList attrs, SilcAttribute attribute); -void silcpurple_get_umode_string(SilcUInt32 mode, char *buf, - SilcUInt32 buf_size); -void silcpurple_get_chmode_string(SilcUInt32 mode, char *buf, - SilcUInt32 buf_size); -void silcpurple_get_chumode_string(SilcUInt32 mode, char *buf, - SilcUInt32 buf_size); -GList *silcpurple_chat_info(PurpleProtocolChat *protocol_chat, PurpleConnection *gc); -GHashTable *silcpurple_chat_info_defaults(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, const char *chat_name); -GList *silcpurple_chat_menu(PurpleChat *); -void silcpurple_chat_join(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, GHashTable *data); -char *silcpurple_get_chat_name(PurpleProtocolChat *protocol_chat, GHashTable *data); -void silcpurple_chat_invite(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int id, const char *msg, - const char *name); -void silcpurple_chat_leave(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int id); -int silcpurple_chat_send(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int id, PurpleMessage *msg); -void silcpurple_chat_set_topic(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int id, const char *topic); -PurpleRoomlist *silcpurple_roomlist_get_list(PurpleProtocolRoomlist *protocol_roomlist, PurpleConnection *gc); -void silcpurple_roomlist_cancel(PurpleProtocolRoomlist *protocol_roomlist, PurpleRoomlist *list); -void silcpurple_chat_chauth_show(SilcPurple sg, SilcChannelEntry channel, - SilcDList channel_pubkeys); -void silcpurple_parse_attrs(SilcDList attrs, char **moodstr, char **statusstr, - char **contactstr, char **langstr, char **devicestr, - char **tzstr, char **geostr); -void silcpurple_buddy_set_icon(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleImage *img); -SilcDList silcpurple_image_message(const char *msg, SilcMessageFlags *mflags); - -#ifdef _WIN32 -typedef int uid_t; - -struct passwd { - char *pw_name; /* user name */ - char *pw_passwd; /* user password */ - int pw_uid; /* user id */ - int pw_gid; /* group id */ - char *pw_gecos; /* real name */ - char *pw_dir; /* home directory */ - char *pw_shell; /* shell program */ -}; - -struct passwd *getpwuid(int uid); -int getuid(void); -int geteuid(void); -#endif - -#endif /* PURPLE_SILC_SILCPURPLE_H */ diff --git a/libpurple/protocols/silc/util.c b/libpurple/protocols/silc/util.c deleted file mode 100644 index 5764d4a031..0000000000 --- a/libpurple/protocols/silc/util.c +++ /dev/null @@ -1,733 +0,0 @@ -/* - - silcpurple_util.c - - Author: Pekka Riikonen <priikone@silcnet.org> - - Copyright (C) 2004 - 2007 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. - -*/ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#ifdef HAVE_FCNTL_H -# include <fcntl.h> -#endif - -#include <glib/gi18n-lib.h> -#include <glib/gstdio.h> - -#include "silcpurple.h" - -/**************************** Utility Routines *******************************/ - -static char str[256], str2[256]; - -const char *silcpurple_silcdir(void) -{ - const char *hd = purple_home_dir(); - memset(str, 0, sizeof(str)); - g_snprintf(str, sizeof(str) - 1, "%s" G_DIR_SEPARATOR_S ".silc", hd ? hd : "/tmp"); - return (const char *)str; -} - -const char *silcpurple_session_file(const char *account) -{ - memset(str2, 0, sizeof(str2)); - g_snprintf(str2, sizeof(str2) - 1, "%s" G_DIR_SEPARATOR_S "%s_session", - silcpurple_silcdir(), account); - return (const char *)str2; -} - -gboolean silcpurple_ip_is_private(const char *ip) -{ - if (silc_net_is_ip4(ip)) { - if (!strncmp(ip, "10.", 3)) { - return TRUE; - } else if (!strncmp(ip, "172.", 4) && strlen(ip) > 6) { - char tmp[3]; - int s; - memset(tmp, 0, sizeof(tmp)); - strncpy(tmp, ip + 4, 2); - s = atoi(tmp); - if (s >= 16 && s <= 31) - return TRUE; - } else if (!strncmp(ip, "192.168.", 8)) { - return TRUE; - } - } - - return FALSE; -} - -/* A fstat alternative, like g_stat for stat. */ -static int -silcpurple_fstat(int fd, GStatBuf *st) -{ - int ret; - - g_return_val_if_fail(st != NULL, -1); - -#ifdef _WIN32 - ret = _fstat(fd, st); -#else - ret = fstat(fd, st); -#endif - - return ret; -} - -/* This checks stats for various SILC files and directories. First it - checks if ~/.silc directory exist and is owned by the correct user. If - it doesn't exist, it will create the directory. After that it checks if - user's Public and Private key files exists and creates them if needed. */ - -gboolean silcpurple_check_silc_dir(PurpleConnection *gc) -{ - char filename[256], file_public_key[256], file_private_key[256]; - char servfilename[256], clientfilename[256], friendsfilename[256]; - char pkd[256], prd[256]; - GStatBuf st; - struct passwd *pw; - int fd; - - pw = getpwuid(getuid()); - if (!pw) { - purple_debug_error("silc", "silc: %s\n", g_strerror(errno)); - return FALSE; - } - - g_snprintf(filename, sizeof(filename) - 1, "%s", silcpurple_silcdir()); - g_snprintf(servfilename, sizeof(servfilename) - 1, "%s" G_DIR_SEPARATOR_S "serverkeys", - silcpurple_silcdir()); - g_snprintf(clientfilename, sizeof(clientfilename) - 1, "%s" G_DIR_SEPARATOR_S "clientkeys", - silcpurple_silcdir()); - g_snprintf(friendsfilename, sizeof(friendsfilename) - 1, "%s" G_DIR_SEPARATOR_S "friends", - silcpurple_silcdir()); - - if (pw->pw_uid != geteuid()) { - purple_debug_error("silc", "Couldn't create directories due to wrong uid!\n"); - return FALSE; - } - - /* - * Check ~/.silc directory - */ - if (g_mkdir(filename, 0755) != 0 && errno != EEXIST) { - purple_debug_error("silc", "Couldn't create '%s' directory\n", filename); - return FALSE; - } - -#ifndef _WIN32 - if ((g_stat(filename, &st)) == -1) { - purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n", filename, g_strerror(errno)); - return FALSE; - } else { - /* Check the owner of the dir */ - if (st.st_uid != 0 && st.st_uid != pw->pw_uid) { - purple_debug_error("silc", "You don't seem to own '%s' directory\n", - filename); - return FALSE; - } - } -#endif - - /* - * Check ~./silc/serverkeys directory - */ - if (g_mkdir(servfilename, 0755) != 0 && errno != EEXIST) { - purple_debug_error("silc", "Couldn't create '%s' directory\n", servfilename); - return FALSE; - } - - /* - * Check ~./silc/clientkeys directory - */ - if (g_mkdir(clientfilename, 0755) != 0 && errno != EEXIST) { - purple_debug_error("silc", "Couldn't create '%s' directory\n", clientfilename); - return FALSE; - } - - /* - * Check ~./silc/friends directory - */ - if (g_mkdir(friendsfilename, 0755) != 0 && errno != EEXIST) { - purple_debug_error("silc", "Couldn't create '%s' directory\n", friendsfilename); - return FALSE; - } - - /* - * Check Public and Private keys - */ - g_snprintf(pkd, sizeof(pkd), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir()); - g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir()); - g_snprintf(file_public_key, sizeof(file_public_key) - 1, "%s", - purple_account_get_string(purple_connection_get_account(gc), "public-key", pkd)); - g_snprintf(file_private_key, sizeof(file_public_key) - 1, "%s", - purple_account_get_string(purple_connection_get_account(gc), "private-key", prd)); - - if ((g_stat(file_public_key, &st)) == -1) { - /* If file doesn't exist */ - if (errno == ENOENT) { - if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS, - SILCPURPLE_DEF_PKCS_LEN, - file_public_key, - file_private_key, NULL, - (purple_connection_get_password(gc) == NULL) ? "" : purple_connection_get_password(gc), - NULL, NULL, FALSE)) { - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, - _("Unable to create SILC key pair")); - return FALSE; - } - - if ((g_stat(file_public_key, &st)) == -1) { - purple_debug_error("silc", "Couldn't stat '%s' public key, error: %s\n", - file_public_key, g_strerror(errno)); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't stat '%s' public key, error: %s\n", - file_public_key, g_strerror(errno)); - return FALSE; - } - } - -#ifndef _WIN32 - /* Check the owner of the public key */ - if (st.st_uid != 0 && st.st_uid != pw->pw_uid) { - purple_debug_error("silc", "You don't seem to own your public key!?\n"); - return FALSE; - } -#endif - - if ((fd = g_open(file_private_key, O_RDONLY, 0)) != -1) { - if (silcpurple_fstat(fd, &st) == -1) { - purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n", - file_private_key, g_strerror(errno)); - close(fd); - return FALSE; - } - } else { - /* If file doesn't exist */ - if (errno == ENOENT) { - if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS, - SILCPURPLE_DEF_PKCS_LEN, - file_public_key, - file_private_key, NULL, - (purple_connection_get_password(gc) == NULL) ? "" : purple_connection_get_password(gc), - NULL, NULL, FALSE)) { - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, - _("Unable to create SILC key pair")); - return FALSE; - } - - if ((fd = g_open(file_private_key, O_RDONLY, 0)) != -1) { - if (silcpurple_fstat(fd, &st) == -1) { - purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n", - file_private_key, g_strerror(errno)); - close(fd); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't open '%s' " - "private key, error: %s\n", - file_private_key, g_strerror(errno)); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't open '%s' private key, error: %s\n", - file_private_key, g_strerror(errno)); - return FALSE; - } - } - -#ifndef _WIN32 - /* Check the owner of the private key */ - if (st.st_uid != 0 && st.st_uid != pw->pw_uid) { - purple_debug_error("silc", "You don't seem to own your private key!?\n"); - if (fd != -1) - close(fd); - return FALSE; - } - - /* Check the permissions for the private key */ - if ((st.st_mode & 0777) != 0600) { - purple_debug_warning("silc", "Wrong permissions in your private key file `%s'!\n" - "Trying to change them ...\n", file_private_key); - if ((fd == -1) || (fchmod(fd, S_IRUSR | S_IWUSR) == -1)) { - purple_debug_error("silc", - "Failed to change permissions for private key file!\n" - "Permissions for your private key file must be 0600.\n"); - if (fd != -1) - close(fd); - return FALSE; - } - purple_debug_warning("silc", "Done.\n\n"); - } -#endif - - if (fd != -1) - close(fd); - -#ifdef _WIN32 - /* on win32, we calloc pw so pass it to free - * (see the getpwuid code below) - */ - free(pw); -#endif - - return TRUE; -} - -#ifdef _WIN32 -struct passwd *getpwuid(uid_t uid) { - struct passwd *pwd = calloc(1, sizeof(struct passwd)); - return pwd; -} - -uid_t getuid() { - return 0; -} - -uid_t geteuid() { - return 0; -} -#endif - -void silcpurple_show_public_key(SilcPurple sg, - const char *name, SilcPublicKey public_key, - GCallback callback, void *context) -{ - SilcPublicKeyIdentifier ident; - SilcSILCPublicKey silc_pubkey; - char *fingerprint, *babbleprint; - unsigned char *pk; - SilcUInt32 pk_len, key_len = 0; - GString *s; - - /* We support showing only SILC public keys for now */ - if (silc_pkcs_get_type(public_key) != SILC_PKCS_SILC) - return; - - silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key); - ident = &silc_pubkey->identifier; - key_len = silc_pkcs_public_key_get_len(public_key); - - pk = silc_pkcs_public_key_encode(public_key, &pk_len); - if (!pk) - return; - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - if (!fingerprint || !babbleprint) - return; - - s = g_string_new(""); - if (ident->realname) - /* Hint for translators: Please check the tabulator width here and in - the next strings (short strings: 2 tabs, longer strings 1 tab, - sum: 3 tabs or 24 characters) */ - g_string_append_printf(s, _("Real Name: \t%s\n"), ident->realname); - if (ident->username) - g_string_append_printf(s, _("User Name: \t%s\n"), ident->username); - if (ident->email) - g_string_append_printf(s, _("Email: \t\t%s\n"), ident->email); - if (ident->host) - g_string_append_printf(s, _("Host Name: \t%s\n"), ident->host); - if (ident->org) - g_string_append_printf(s, _("Organization: \t%s\n"), ident->org); - if (ident->country) - g_string_append_printf(s, _("Country: \t%s\n"), ident->country); - g_string_append_printf(s, _("Algorithm: \t%s\n"), silc_pubkey->pkcs->name); - g_string_append_printf(s, _("Key Length: \t%d bits\n"), (int)key_len); - if (ident->version) - g_string_append_printf(s, _("Version: \t%s\n"), ident->version); - g_string_append_printf(s, "\n"); - g_string_append_printf(s, _("Public Key Fingerprint:\n%s\n\n"), fingerprint); - g_string_append_printf(s, _("Public Key Babbleprint:\n%s"), babbleprint); - - purple_request_action(sg->gc, _("Public Key Information"), - _("Public Key Information"), - s->str, 0, purple_request_cpar_from_connection(sg->gc), - context, 1, _("Close"), callback); - - g_string_free(s, TRUE); - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); -} - -SilcAttributePayload -silcpurple_get_attr(SilcDList attrs, SilcAttribute attribute) -{ - SilcAttributePayload attr = NULL; - - if (!attrs) - return NULL; - - silc_dlist_start(attrs); - while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) - if (attribute == silc_attribute_get_attribute(attr)) - break; - - return attr; -} - -void silcpurple_get_umode_string(SilcUInt32 mode, char *buf, - SilcUInt32 buf_size) -{ - memset(buf, 0, buf_size); - if ((mode & SILC_UMODE_SERVER_OPERATOR) || - (mode & SILC_UMODE_ROUTER_OPERATOR)) { - strcat(buf, (mode & SILC_UMODE_SERVER_OPERATOR) ? - "[server operator] " : - (mode & SILC_UMODE_ROUTER_OPERATOR) ? - "[SILC operator] " : "[unknown mode] "); - } - if (mode & SILC_UMODE_GONE) - strcat(buf, "[away] "); - if (mode & SILC_UMODE_INDISPOSED) - strcat(buf, "[indisposed] "); - if (mode & SILC_UMODE_BUSY) - strcat(buf, "[busy] "); - if (mode & SILC_UMODE_PAGE) - strcat(buf, "[wake me up] "); - if (mode & SILC_UMODE_HYPER) - strcat(buf, "[hyperactive] "); - if (mode & SILC_UMODE_ROBOT) - strcat(buf, "[robot] "); - if (mode & SILC_UMODE_ANONYMOUS) - strcat(buf, "[anonymous] "); - if (mode & SILC_UMODE_BLOCK_PRIVMSG) - strcat(buf, "[blocks private messages] "); - if (mode & SILC_UMODE_DETACHED) - strcat(buf, "[detached] "); - if (mode & SILC_UMODE_REJECT_WATCHING) - strcat(buf, "[rejects watching] "); - if (mode & SILC_UMODE_BLOCK_INVITE) - strcat(buf, "[blocks invites] "); - g_strchomp(buf); -} - -void silcpurple_get_chmode_string(SilcUInt32 mode, char *buf, - SilcUInt32 buf_size) -{ - memset(buf, 0, buf_size); - if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) - strcat(buf, "[permanent] "); - if (mode & SILC_CHANNEL_MODE_PRIVATE) - strcat(buf, "[private] "); - if (mode & SILC_CHANNEL_MODE_SECRET) - strcat(buf, "[secret] "); - if (mode & SILC_CHANNEL_MODE_PRIVKEY) - strcat(buf, "[private key] "); - if (mode & SILC_CHANNEL_MODE_INVITE) - strcat(buf, "[invite only] "); - if (mode & SILC_CHANNEL_MODE_TOPIC) - strcat(buf, "[topic restricted] "); - if (mode & SILC_CHANNEL_MODE_ULIMIT) - strcat(buf, "[user count limit] "); - if (mode & SILC_CHANNEL_MODE_PASSPHRASE) - strcat(buf, "[passphrase auth] "); - if (mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) - strcat(buf, "[public key auth] "); - if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) - strcat(buf, "[users silenced] "); - if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) - strcat(buf, "[operators silenced] "); - g_strchomp(buf); -} - -void silcpurple_get_chumode_string(SilcUInt32 mode, char *buf, - SilcUInt32 buf_size) -{ - memset(buf, 0, buf_size); - if (mode & SILC_CHANNEL_UMODE_CHANFO) - strcat(buf, "[founder] "); - if (mode & SILC_CHANNEL_UMODE_CHANOP) - strcat(buf, "[operator] "); - if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) - strcat(buf, "[blocks messages] "); - if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) - strcat(buf, "[blocks user messages] "); - if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) - strcat(buf, "[blocks robot messages] "); - if (mode & SILC_CHANNEL_UMODE_QUIET) - strcat(buf, "[quieted] "); - g_strchomp(buf); -} - -void -silcpurple_parse_attrs(SilcDList attrs, char **moodstr, char **statusstr, - char **contactstr, char **langstr, char **devicestr, - char **tzstr, char **geostr) -{ - SilcAttributePayload attr; - SilcAttributeMood mood = 0; - SilcAttributeContact contact; - SilcAttributeObjDevice device; - SilcAttributeObjGeo geo; - - char tmp[1024]; - GString *s; - - *moodstr = NULL; - *statusstr = NULL; - *contactstr = NULL; - *langstr = NULL; - *devicestr = NULL; - *tzstr = NULL; - *geostr = NULL; - - if (!attrs) - return; - - s = g_string_new(""); - attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_STATUS_MOOD); - if (attr && silc_attribute_get_object(attr, &mood, sizeof(mood))) { - if (mood & SILC_ATTRIBUTE_MOOD_HAPPY) - g_string_append_printf(s, "[%s] ", _("Happy")); - if (mood & SILC_ATTRIBUTE_MOOD_SAD) - g_string_append_printf(s, "[%s] ", _("Sad")); - if (mood & SILC_ATTRIBUTE_MOOD_ANGRY) - g_string_append_printf(s, "[%s] ", _("Angry")); - if (mood & SILC_ATTRIBUTE_MOOD_JEALOUS) - g_string_append_printf(s, "[%s] ", _("Jealous")); - if (mood & SILC_ATTRIBUTE_MOOD_ASHAMED) - g_string_append_printf(s, "[%s] ", _("Ashamed")); - if (mood & SILC_ATTRIBUTE_MOOD_INVINCIBLE) - g_string_append_printf(s, "[%s] ", _("Invincible")); - if (mood & SILC_ATTRIBUTE_MOOD_INLOVE) - g_string_append_printf(s, "[%s] ", _("In Love")); - if (mood & SILC_ATTRIBUTE_MOOD_SLEEPY) - g_string_append_printf(s, "[%s] ", _("Sleepy")); - if (mood & SILC_ATTRIBUTE_MOOD_BORED) - g_string_append_printf(s, "[%s] ", _("Bored")); - if (mood & SILC_ATTRIBUTE_MOOD_EXCITED) - g_string_append_printf(s, "[%s] ", _("Excited")); - if (mood & SILC_ATTRIBUTE_MOOD_ANXIOUS) - g_string_append_printf(s, "[%s] ", _("Anxious")); - } - if (*s->str != '\0') { - *moodstr = g_string_free(s, FALSE); - g_strchomp(*moodstr); - } else - g_string_free(s, TRUE); - - attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_STATUS_FREETEXT); - memset(tmp, 0, sizeof(tmp)); - if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp))) - *statusstr = g_strdup(tmp); - - s = g_string_new(""); - attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_PREFERRED_CONTACT); - if (attr && silc_attribute_get_object(attr, &contact, sizeof(contact))) { - if (contact & SILC_ATTRIBUTE_CONTACT_CHAT) - g_string_append_printf(s, "[%s] ", _("Chat")); - if (contact & SILC_ATTRIBUTE_CONTACT_EMAIL) - g_string_append_printf(s, "[%s] ", _("Email")); - if (contact & SILC_ATTRIBUTE_CONTACT_CALL) - g_string_append_printf(s, "[%s] ", _("Phone")); - if (contact & SILC_ATTRIBUTE_CONTACT_PAGE) - g_string_append_printf(s, "[%s] ", _("Paging")); - if (contact & SILC_ATTRIBUTE_CONTACT_SMS) - g_string_append_printf(s, "[%s] ", _("SMS")); - if (contact & SILC_ATTRIBUTE_CONTACT_MMS) - g_string_append_printf(s, "[%s] ", _("MMS")); - if (contact & SILC_ATTRIBUTE_CONTACT_VIDEO) - g_string_append_printf(s, "[%s] ", _("Video Conferencing")); - } - if (*s->str != '\0') { - *contactstr = g_string_free(s, FALSE); - g_strchomp(*contactstr); - } else - g_string_free(s, TRUE); - - attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_PREFERRED_LANGUAGE); - memset(tmp, 0, sizeof(tmp)); - if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp))) - *langstr = g_strdup(tmp); - - s = g_string_new(""); - attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_DEVICE_INFO); - memset(&device, 0, sizeof(device)); - if (attr && silc_attribute_get_object(attr, &device, sizeof(device))) { - if (device.type == SILC_ATTRIBUTE_DEVICE_COMPUTER) - g_string_append_printf(s, "%s: ", _("Computer")); - if (device.type == SILC_ATTRIBUTE_DEVICE_MOBILE_PHONE) - g_string_append_printf(s, "%s: ", _("Mobile Phone")); - if (device.type == SILC_ATTRIBUTE_DEVICE_PDA) - g_string_append_printf(s, "%s: ", _("PDA")); - if (device.type == SILC_ATTRIBUTE_DEVICE_TERMINAL) - g_string_append_printf(s, "%s: ", _("Terminal")); - g_string_append_printf(s, "%s %s %s %s", - device.manufacturer ? device.manufacturer : "", - device.version ? device.version : "", - device.model ? device.model : "", - device.language ? device.language : ""); - } - if (*s->str != '\0') - *devicestr = g_string_free(s, FALSE); - else - g_string_free(s, TRUE); - - attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_TIMEZONE); - memset(tmp, 0, sizeof(tmp)); - if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp))) - *tzstr = g_strdup(tmp); - - attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_GEOLOCATION); - memset(&geo, 0, sizeof(geo)); - if (attr && silc_attribute_get_object(attr, &geo, sizeof(geo))) - *geostr = g_strdup_printf("%s %s %s (%s)", - geo.longitude ? geo.longitude : "", - geo.latitude ? geo.latitude : "", - geo.altitude ? geo.altitude : "", - geo.accuracy ? geo.accuracy : ""); -} - -/* Checks if message has images, and assembles MIME message if it has. - If only one image is present, creates simple MIME image message. If - there are multiple images and/or text with images multipart MIME - message is created. */ - -SilcDList silcpurple_image_message(const char *msg, SilcMessageFlags *mflags) -{ - SilcMime mime = NULL, p; - SilcDList list, parts = NULL; - const char *start, *end, *last; - GData *attribs; - gboolean images = FALSE; - - last = msg; - while (last && *last && purple_markup_find_tag("img", last, &start, - &end, &attribs)) { - PurpleImage *image = NULL; - const gchar *uri; - - /* Check if there is text before image */ - if (start - last) { - char *text, *tmp; - p = silc_mime_alloc(); - - /* Add content type */ - silc_mime_add_field(p, "Content-Type", - "text/plain; charset=utf-8"); - - tmp = g_strndup(last, start - last); - text = purple_unescape_html(tmp); - g_free(tmp); - - /* Add text */ - silc_mime_add_data(p, (const unsigned char *)text, strlen(text)); - g_free(text); - - if (!parts) - parts = silc_dlist_init(); - silc_dlist_add(parts, p); - } - - uri = g_datalist_get_data(&attribs, "src"); - if (uri) - image = purple_image_store_get_from_uri(uri); - if (uri) { - unsigned long imglen = purple_image_get_data_size(image); - gconstpointer img = purple_image_get_data(image); - const gchar *type; - - p = silc_mime_alloc(); - - /* Add content type */ - type = purple_image_get_mimetype(image); - if (!type) { - g_datalist_clear(&attribs); - last = end + 1; - continue; - } - silc_mime_add_field(p, "Content-Type", type); - - /* Add content transfer encoding */ - silc_mime_add_field(p, "Content-Transfer-Encoding", "binary"); - - /* Add image data */ - silc_mime_add_data(p, img, imglen); - - if (!parts) - parts = silc_dlist_init(); - silc_dlist_add(parts, p); - images = TRUE; - } - - g_datalist_clear(&attribs); - - /* Continue after tag */ - last = end + 1; - } - - /* Check for text after the image(s) */ - if (images && last && *last) { - char *tmp = purple_unescape_html(last); - p = silc_mime_alloc(); - - /* Add content type */ - silc_mime_add_field(p, "Content-Type", - "text/plain; charset=utf-8"); - - /* Add text */ - silc_mime_add_data(p, (const unsigned char *)tmp, strlen(tmp)); - g_free(tmp); - - if (!parts) - parts = silc_dlist_init(); - silc_dlist_add(parts, p); - } - - /* If there weren't any images, don't return anything. */ - if (!images) { - if (parts) - silc_dlist_uninit(parts); - return NULL; - } - - if (silc_dlist_count(parts) > 1) { - /* Multipart MIME message */ - char b[32]; - mime = silc_mime_alloc(); - silc_mime_add_field(mime, "MIME-Version", "1.0"); - g_snprintf(b, sizeof(b), "b%4X%4X", - (unsigned int)time(NULL), - silc_dlist_count(parts)); - silc_mime_set_multipart(mime, "mixed", b); - silc_dlist_start(parts); - while ((p = silc_dlist_get(parts)) != SILC_LIST_END) - silc_mime_add_multipart(mime, p); - } else { - /* Simple MIME message */ - silc_dlist_start(parts); - mime = silc_dlist_get(parts); - silc_mime_add_field(mime, "MIME-Version", "1.0"); - } - - *mflags &= ~SILC_MESSAGE_FLAG_UTF8; - *mflags |= SILC_MESSAGE_FLAG_DATA; - - /* Encode message. Fragment if it is too large */ - list = silc_mime_encode_partial(mime, 0xfc00); - - silc_dlist_uninit(parts); - - /* Added multiparts gets freed here */ - silc_mime_free(mime); - - return list; -} diff --git a/libpurple/protocols/silc/wb.c b/libpurple/protocols/silc/wb.c deleted file mode 100644 index 80577acfd1..0000000000 --- a/libpurple/protocols/silc/wb.c +++ /dev/null @@ -1,547 +0,0 @@ -/* - - wb.c - - Author: Pekka Riikonen <priikone@silcnet.org> - - Copyright (C) 2005 - 2007 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. - -*/ - -#include <glib/gi18n-lib.h> - -#include "silcpurple.h" -#include "wb.h" - -/* - SILC Whiteboard packet: - - 1 byte command - 2 bytes width - 2 bytes height - 4 bytes brush color - 2 bytes brush size - n bytes data - - Data: - - 4 bytes x - 4 bytes y - - Commands: - - 0x01 draw - 0x02 clear - - MIME: - - MIME-Version: 1.0 - Content-Type: application/x-wb - Content-Transfer-Encoding: binary - -*/ - -#define SILCPURPLE_WB_MIME "MIME-Version: 1.0\r\nContent-Type: application/x-wb\r\nContent-Transfer-Encoding: binary\r\n\r\n" -#define SILCPURPLE_WB_HEADER strlen(SILCPURPLE_WB_MIME) + 11 - -#define SILCPURPLE_WB_WIDTH 500 -#define SILCPURPLE_WB_HEIGHT 400 -#define SILCPURPLE_WB_WIDTH_MAX 1024 -#define SILCPURPLE_WB_HEIGHT_MAX 1024 - -/* Commands */ -typedef enum { - SILCPURPLE_WB_DRAW = 0x01, - SILCPURPLE_WB_CLEAR = 0x02, -} SilcPurpleWbCommand; - -/* Brush size */ -typedef enum { - SILCPURPLE_WB_BRUSH_SMALL = 2, - SILCPURPLE_WB_BRUSH_MEDIUM = 5, - SILCPURPLE_WB_BRUSH_LARGE = 10, -} SilcPurpleWbBrushSize; - -/* Brush color (XXX Purple should provide default colors) */ -typedef enum { - SILCPURPLE_WB_COLOR_BLACK = 0, - SILCPURPLE_WB_COLOR_RED = 13369344, - SILCPURPLE_WB_COLOR_GREEN = 52224, - SILCPURPLE_WB_COLOR_BLUE = 204, - SILCPURPLE_WB_COLOR_YELLOW = 15658496, - SILCPURPLE_WB_COLOR_ORANGE = 16737792, - SILCPURPLE_WB_COLOR_CYAN = 52428, - SILCPURPLE_WB_COLOR_VIOLET = 5381277, - SILCPURPLE_WB_COLOR_PURPLE = 13369548, - SILCPURPLE_WB_COLOR_TAN = 12093547, - SILCPURPLE_WB_COLOR_BROWN = 5256485, - SILCPURPLE_WB_COLOR_GREY = 11184810, - SILCPURPLE_WB_COLOR_WHITE = 16777215, -} SilcPurpleWbColor; - -typedef struct { - int type; /* 0 = buddy, 1 = channel */ - union { - SilcClientEntry client; - SilcChannelEntry channel; - } u; - int width; - int height; - int brush_size; - int brush_color; -} *SilcPurpleWb; - -/* Initialize whiteboard */ - -PurpleWhiteboard *silcpurple_wb_init(SilcPurple sg, SilcClientEntry client_entry) -{ - PurpleWhiteboard *wb; - PurpleWhiteboardManager *manager; - SilcPurpleWb wbs; - gchar *id = NULL; - - manager = purple_whiteboard_manager_get_default(); - - id = g_strdup_printf("silc-client-%s", client_entry->nickname); - wb = purple_whiteboard_manager_find(manager, id); - if(!PURPLE_IS_WHITEBOARD(wb)) { - wb = purple_whiteboard_new(sg->account, id, 0); - purple_whiteboard_manager_register(manager, wb, NULL); - } - - g_free(id); - - if(!PURPLE_IS_WHITEBOARD(wb)) { - return NULL; - } - - if (!purple_whiteboard_get_protocol_data(wb)) { - wbs = silc_calloc(1, sizeof(*wbs)); - if (!wbs) - return NULL; - wbs->type = 0; - wbs->u.client = client_entry; - wbs->width = SILCPURPLE_WB_WIDTH; - wbs->height = SILCPURPLE_WB_HEIGHT; - wbs->brush_size = SILCPURPLE_WB_BRUSH_SMALL; - wbs->brush_color = SILCPURPLE_WB_COLOR_BLACK; - purple_whiteboard_set_protocol_data(wb, wbs); - - /* Start the whiteboard */ - purple_whiteboard_start(wb); - purple_whiteboard_clear(wb); - } - - return wb; -} - -PurpleWhiteboard *silcpurple_wb_init_ch(SilcPurple sg, SilcChannelEntry channel) -{ - PurpleWhiteboardManager *manager = NULL; - PurpleWhiteboard *wb; - SilcPurpleWb wbs; - gchar *id; - - manager = purple_whiteboard_manager_get_default(); - - id = g_strdup_printf("silc-channel-%s", channel->channel_name); - wb = purple_whiteboard_manager_find(manager, id); - if(!PURPLE_IS_WHITEBOARD(wb)) { - wb = purple_whiteboard_new(sg->account, id, 0); - } - - g_free(id); - - if(!PURPLE_IS_WHITEBOARD(wb)) { - return NULL; - } - - if (!purple_whiteboard_get_protocol_data(wb)) { - wbs = silc_calloc(1, sizeof(*wbs)); - if (!wbs) - return NULL; - wbs->type = 1; - wbs->u.channel = channel; - wbs->width = SILCPURPLE_WB_WIDTH; - wbs->height = SILCPURPLE_WB_HEIGHT; - wbs->brush_size = SILCPURPLE_WB_BRUSH_SMALL; - wbs->brush_color = SILCPURPLE_WB_COLOR_BLACK; - purple_whiteboard_set_protocol_data(wb, wbs); - - /* Start the whiteboard */ - purple_whiteboard_start(wb); - purple_whiteboard_clear(wb); - } - - return wb; -} - -static void -silcpurple_wb_parse(PurpleWhiteboard *wb, - unsigned char *message, SilcUInt32 message_len) -{ - SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb); - SilcUInt8 command; - SilcUInt16 width, height, brush_size; - SilcUInt32 brush_color, x, y, dx, dy; - SilcBufferStruct buf; - int ret; - - /* Parse the packet */ - silc_buffer_set(&buf, message, message_len); - ret = silc_buffer_unformat(&buf, - SILC_STR_UI_CHAR(&command), - SILC_STR_UI_SHORT(&width), - SILC_STR_UI_SHORT(&height), - SILC_STR_UI_INT(&brush_color), - SILC_STR_UI_SHORT(&brush_size), - SILC_STR_END); - if (ret < 0) - return; - silc_buffer_pull(&buf, ret); - - /* Update whiteboard if its dimensions changed */ - if (width != wbs->width || height != wbs->height) - silcpurple_wb_set_dimensions(wb, width, height); - - if (command == SILCPURPLE_WB_DRAW) { - /* Parse data and draw it */ - ret = silc_buffer_unformat(&buf, - SILC_STR_UI_INT(&dx), - SILC_STR_UI_INT(&dy), - SILC_STR_END); - if (ret < 0) - return; - silc_buffer_pull(&buf, 8); - x = dx; - y = dy; - while (silc_buffer_len(&buf) > 0) { - ret = silc_buffer_unformat(&buf, - SILC_STR_UI_INT(&dx), - SILC_STR_UI_INT(&dy), - SILC_STR_END); - if (ret < 0) - return; - silc_buffer_pull(&buf, 8); - - purple_whiteboard_draw_line(wb, x, y, x + dx, y + dy, - brush_color, brush_size); - x += dx; - y += dy; - } - } - - if (command == SILCPURPLE_WB_CLEAR) - purple_whiteboard_clear(wb); -} - -typedef struct { - unsigned char *message; - SilcUInt32 message_len; - SilcPurple sg; - SilcClientEntry sender; - SilcChannelEntry channel; -} *SilcPurpleWbRequest; - -static void -silcpurple_wb_request_cb(SilcPurpleWbRequest req, gint id) -{ - PurpleWhiteboard *wb; - - if (id != 1) - goto out; - - if (!req->channel) - wb = silcpurple_wb_init(req->sg, req->sender); - else - wb = silcpurple_wb_init_ch(req->sg, req->channel); - - silcpurple_wb_parse(wb, req->message, req->message_len); - - out: - silc_free(req->message); - silc_free(req); -} - -static void -silcpurple_wb_request(SilcClient client, const unsigned char *message, - SilcUInt32 message_len, SilcClientEntry sender, - SilcChannelEntry channel) -{ - char tmp[256]; - SilcPurpleWbRequest req; - PurpleConnection *gc; - SilcPurple sg; - - gc = client->application; - sg = purple_connection_get_protocol_data(gc); - - /* Open whiteboard automatically if requested */ - if (purple_account_get_bool(sg->account, "open-wb", FALSE)) { - PurpleWhiteboard *wb; - - if (!channel) - wb = silcpurple_wb_init(sg, sender); - else - wb = silcpurple_wb_init_ch(sg, channel); - - silcpurple_wb_parse(wb, - (unsigned char *)message, - message_len); - return; - } - - /* Close any previous unaccepted requests */ - purple_request_close_with_handle(sender); - - if (!channel) { - g_snprintf(tmp, sizeof(tmp), - _("%s sent message to whiteboard. Would you like " - "to open the whiteboard?"), sender->nickname); - } else { - g_snprintf(tmp, sizeof(tmp), - _("%s sent message to whiteboard on %s channel. " - "Would you like to open the whiteboard?"), - sender->nickname, channel->channel_name); - } - - req = silc_calloc(1, sizeof(*req)); - if (!req) - return; - req->message = silc_memdup(message, message_len); - req->message_len = message_len; - req->sender = sender; - req->channel = channel; - req->sg = sg; - - purple_request_action(gc, _("Whiteboard"), tmp, NULL, 1, - purple_request_cpar_from_connection(gc), req, 2, - _("Yes"), G_CALLBACK(silcpurple_wb_request_cb), - _("No"), G_CALLBACK(silcpurple_wb_request_cb)); -} - -/* Process incoming whiteboard message */ - -void silcpurple_wb_receive(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcMessagePayload payload, - SilcMessageFlags flags, const unsigned char *message, - SilcUInt32 message_len) -{ - PurpleWhiteboard *wb; - PurpleWhiteboardManager *manager; - gchar *id = NULL; - - manager = purple_whiteboard_manager_get_default(); - - id = g_strdup_printf("silc-client-%s", sender->nickname); - wb = purple_whiteboard_manager_find(manager, id); - g_free(id); - - if(!PURPLE_IS_WHITEBOARD(wb)) { - /* Ask user if they want to open the whiteboard */ - silcpurple_wb_request(client, message, message_len, sender, NULL); - return; - } - - silcpurple_wb_parse(wb, (unsigned char *)message, message_len); -} - -/* Process incoming whiteboard message on channel */ - -void silcpurple_wb_receive_ch(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcChannelEntry channel, - SilcMessagePayload payload, - SilcMessageFlags flags, - const unsigned char *message, - SilcUInt32 message_len) -{ - PurpleWhiteboard *wb; - PurpleWhiteboardManager *manager; - gchar *id; - - manager = purple_whiteboard_manager_get_default(); - - id = g_strdup_printf("silc-channel-%s", channel->channel_name); - wb = purple_whiteboard_manager_find(manager, id); - g_free(id); - - if(!PURPLE_IS_WHITEBOARD(wb)) { - /* Ask user if they want to open the whiteboard */ - silcpurple_wb_request(client, message, message_len, sender, channel); - - return; - } - - silcpurple_wb_parse(wb, (unsigned char *)message, message_len); -} - -/* Send whiteboard message */ - -void silcpurple_wb_send(PurpleWhiteboard *wb, GList *draw_list) -{ - SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb); - SilcBuffer packet; - GList *list; - int len; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(draw_list); - gc = purple_account_get_connection(purple_whiteboard_get_account(wb)); - g_return_if_fail(gc); - sg = purple_connection_get_protocol_data(gc); - g_return_if_fail(sg); - - len = SILCPURPLE_WB_HEADER; - for (list = draw_list; list; list = list->next) - len += 4; - - packet = silc_buffer_alloc_size(len); - if (!packet) - return; - - /* Assmeble packet */ - silc_buffer_format(packet, - SILC_STR_UI32_STRING(SILCPURPLE_WB_MIME), - SILC_STR_UI_CHAR(SILCPURPLE_WB_DRAW), - SILC_STR_UI_SHORT(wbs->width), - SILC_STR_UI_SHORT(wbs->height), - SILC_STR_UI_INT(wbs->brush_color), - SILC_STR_UI_SHORT(wbs->brush_size), - SILC_STR_END); - silc_buffer_pull(packet, SILCPURPLE_WB_HEADER); - for (list = draw_list; list; list = list->next) { - silc_buffer_format(packet, - SILC_STR_UI_INT(GPOINTER_TO_INT(list->data)), - SILC_STR_END); - silc_buffer_pull(packet, 4); - } - - /* Send the message */ - if (wbs->type == 0) { - /* Private message */ - silc_client_send_private_message(sg->client, sg->conn, - wbs->u.client, - SILC_MESSAGE_FLAG_DATA, NULL, - packet->head, len); - } else if (wbs->type == 1) { - /* Channel message. Channel private keys are not supported. */ - silc_client_send_channel_message(sg->client, sg->conn, - wbs->u.channel, NULL, - SILC_MESSAGE_FLAG_DATA, NULL, - packet->head, len); - } - - silc_buffer_free(packet); -} - -/* Purple Whiteboard operations */ - -void silcpurple_wb_start(PurpleWhiteboard *wb) -{ - /* Nothing here. Everything is in initialization */ -} - -void silcpurple_wb_end(PurpleWhiteboard *wb) -{ - SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb); - PurpleWhiteboardManager *manager; - - manager = purple_whiteboard_manager_get_default(); - - silc_free(wbs); - purple_whiteboard_set_protocol_data(wb, NULL); - - purple_whiteboard_manager_unregister(manager, wb, NULL); -} - -void silcpurple_wb_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height) -{ - SilcPurpleWb wbs = purple_whiteboard_get_protocol_data((PurpleWhiteboard *)wb); - *width = wbs->width; - *height = wbs->height; -} - -void silcpurple_wb_set_dimensions(PurpleWhiteboard *wb, int width, int height) -{ - SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb); - wbs->width = width > SILCPURPLE_WB_WIDTH_MAX ? SILCPURPLE_WB_WIDTH_MAX : - width; - wbs->height = height > SILCPURPLE_WB_HEIGHT_MAX ? SILCPURPLE_WB_HEIGHT_MAX : - height; - - /* Update whiteboard */ - purple_whiteboard_set_dimensions(wb, wbs->width, wbs->height); -} - -void silcpurple_wb_get_brush(const PurpleWhiteboard *wb, int *size, int *color) -{ - SilcPurpleWb wbs = purple_whiteboard_get_protocol_data((PurpleWhiteboard *)wb); - *size = wbs->brush_size; - *color = wbs->brush_color; -} - -void silcpurple_wb_set_brush(PurpleWhiteboard *wb, int size, int color) -{ - SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb); - wbs->brush_size = size; - wbs->brush_color = color; - - /* Update whiteboard */ - purple_whiteboard_set_brush(wb, size, color); -} - -void silcpurple_wb_clear(PurpleWhiteboard *wb) -{ - SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb); - SilcBuffer packet; - int len; - PurpleConnection *gc; - SilcPurple sg; - - gc = purple_account_get_connection(purple_whiteboard_get_account(wb)); - g_return_if_fail(gc); - sg = purple_connection_get_protocol_data(gc); - g_return_if_fail(sg); - - len = SILCPURPLE_WB_HEADER; - packet = silc_buffer_alloc_size(len); - if (!packet) - return; - - /* Assmeble packet */ - silc_buffer_format(packet, - SILC_STR_UI32_STRING(SILCPURPLE_WB_MIME), - SILC_STR_UI_CHAR(SILCPURPLE_WB_CLEAR), - SILC_STR_UI_SHORT(wbs->width), - SILC_STR_UI_SHORT(wbs->height), - SILC_STR_UI_INT(wbs->brush_color), - SILC_STR_UI_SHORT(wbs->brush_size), - SILC_STR_END); - - /* Send the message */ - if (wbs->type == 0) { - /* Private message */ - silc_client_send_private_message(sg->client, sg->conn, - wbs->u.client, - SILC_MESSAGE_FLAG_DATA, NULL, - packet->head, len); - } else if (wbs->type == 1) { - /* Channel message */ - silc_client_send_channel_message(sg->client, sg->conn, - wbs->u.channel, NULL, - SILC_MESSAGE_FLAG_DATA, NULL, - packet->head, len); - } - - silc_buffer_free(packet); -} diff --git a/libpurple/protocols/silc/wb.h b/libpurple/protocols/silc/wb.h deleted file mode 100644 index fd566a1acf..0000000000 --- a/libpurple/protocols/silc/wb.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - - silcpurple.h - - Author: Pekka Riikonen <priikone@silcnet.org> - - Copyright (C) 2005 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 PURPLE_SILC_WB_H -#define PURPLE_SILC_WB_H - -#include "silcpurple.h" - -PurpleWhiteboard * -silcpurple_wb_init(SilcPurple sg, SilcClientEntry client_entry); -PurpleWhiteboard * -silcpurple_wb_init_ch(SilcPurple sg, SilcChannelEntry channel); -void silcpurple_wb_receive(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcMessagePayload payload, - SilcMessageFlags flags, const unsigned char *message, - SilcUInt32 message_len); -void silcpurple_wb_receive_ch(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcChannelEntry channel, - SilcMessagePayload payload, - SilcMessageFlags flags, - const unsigned char *message, - SilcUInt32 message_len); -void silcpurple_wb_start(PurpleWhiteboard *wb); -void silcpurple_wb_end(PurpleWhiteboard *wb); -void silcpurple_wb_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height); -void silcpurple_wb_set_dimensions(PurpleWhiteboard *wb, int width, int height); -void silcpurple_wb_get_brush(const PurpleWhiteboard *wb, int *size, int *color); -void silcpurple_wb_set_brush(PurpleWhiteboard *wb, int size, int color); -void silcpurple_wb_send(PurpleWhiteboard *wb, GList *draw_list); -void silcpurple_wb_clear(PurpleWhiteboard *wb); - -#endif /* PURPLE_SILC_WB_H */ diff --git a/meson.build b/meson.build index c9c2656833..53b4fbdc9b 100644 --- a/meson.build +++ b/meson.build @@ -340,12 +340,6 @@ else enable_avahi = avahi_client.found() and avahi_glib.found() endif - -####################################################################### -# Check for SILC client includes and libraries -####################################################################### -silc = dependency('silcclient', version : '>= 1.1.1', required : get_option('silc')) - ####################################################################### # Check for Gadu-Gadu protocol library (libgadu) ####################################################################### @@ -370,7 +364,7 @@ endif DEFAULT_PRPLS = ['bonjour', 'demo', 'facebook', 'gg', 'irc', 'ircv3', 'jabber', - 'novell', 'null', 'sametime', 'silc', 'zephyr'] + 'novell', 'null', 'sametime', 'zephyr'] ALL_PRPLS = DEFAULT_PRPLS + ['null'] dynamic_list = get_option('dynamic-prpls').split(',') @@ -385,8 +379,6 @@ foreach prpl : dynamic_list # Do nothing. elif prpl == 'bonjour' and not enable_avahi # Do nothing. - elif prpl == 'silc' and not silc.found() - # Do nothing. elif prpl == 'gg' and not libgadu.found() # Do nothing. elif prpl == 'zephyr' and IS_WIN32 @@ -406,7 +398,6 @@ DYNAMIC_JABBER = DYNAMIC_PRPLS.contains('jabber') DYNAMIC_NOVELL = DYNAMIC_PRPLS.contains('novell') DYNAMIC_NULL = DYNAMIC_PRPLS.contains('null') DYNAMIC_SAMETIME = DYNAMIC_PRPLS.contains('sametime') -DYNAMIC_SILC = DYNAMIC_PRPLS.contains('silc') DYNAMIC_ZEPHYR = DYNAMIC_PRPLS.contains('zephyr') conf.set('HAVE_SYS_UTSNAME_H', diff --git a/meson_options.txt b/meson_options.txt index 44d83769b1..3d0ad5889d 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -46,9 +46,6 @@ option('libgadu', type : 'feature', option('meanwhile', type : 'feature', description : 'compile with meanwhile') -option('silc', type : 'feature', - description : 'compile with SILC plugin') - option('zephyr', type : 'feature', description : 'compile Zephyr plugin against external libzephyr') diff --git a/pidgin/data/im.pidgin.Pidgin3.desktop.in.in b/pidgin/data/im.pidgin.Pidgin3.desktop.in.in index 77078943a6..10b986582a 100644 --- a/pidgin/data/im.pidgin.Pidgin3.desktop.in.in +++ b/pidgin/data/im.pidgin.Pidgin3.desktop.in.in @@ -4,7 +4,7 @@ GenericName=Internet Messenger X-GNOME-FullName=Pidgin Internet Messenger Comment=Chat over IM. Supports XMPP, IRC, and more # TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! -Keywords=chat;talk;im;message;bonjour;gadu-gadu;irc;groupwise;jabber;sametime;silc;simple;xmpp;zephyr +Keywords=chat;talk;im;message;bonjour;gadu-gadu;irc;groupwise;jabber;sametime;simple;xmpp;zephyr Exec=pidgin3 %U Icon=im.pidgin.Pidgin3 StartupNotify=true diff --git a/po/POTFILES.in b/po/POTFILES.in index a47dbde3a5..b7a6a1f811 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -174,14 +174,6 @@ libpurple/protocols/novell/novell.c libpurple/protocols/sametime/im_mime.c libpurple/protocols/sametime/sametime.c libpurple/protocols/sametime/tests/test_sametime_im_mime.c -libpurple/protocols/silc/buddy.c -libpurple/protocols/silc/chat.c -libpurple/protocols/silc/ft.c -libpurple/protocols/silc/ops.c -libpurple/protocols/silc/pk.c -libpurple/protocols/silc/silc.c -libpurple/protocols/silc/util.c -libpurple/protocols/silc/wb.c libpurple/protocols/zephyr/ZAsyncLocate.c libpurple/protocols/zephyr/ZCkAuth.c libpurple/protocols/zephyr/ZCkIfNot.c |