# HG changeset patch # User Mark Doliner # Date 1313996487 0 # Node ID 4f2d99bcb1955007381865bc12077214eed2c5dc # Parent 0cc718e10344ec70e2d39c0eb38107f246e691bf Remove silc10 diff -r 0cc718e10344 -r 4f2d99bcb195 configure.ac --- a/configure.ac Mon Aug 22 06:32:44 2011 +0000 +++ b/configure.ac Mon Aug 22 07:01:27 2011 +0000 @@ -941,25 +941,6 @@ ], [ have_silc="no" ]) - if test "x$have_silc" = "xno"; then - PKG_CHECK_MODULES(SILC, silcclient, [ - have_silc="yes" - silc10includes="yes" - silc10client="yes" - ], [ - have_silc="no" - ]) - dnl If silcclient.pc wasn't found, check for just silc.pc - if test "x$have_silc" = "xno"; then - PKG_CHECK_MODULES(SILC, silc, [ - have_silc="yes" - silc10includes="yes" - silc10client="yes" - ], [ - have_silc="no" - ]) - fi - fi else if test "$ac_silc_includes" != "no"; then SILC_CFLAGS="-I$ac_silc_includes" @@ -977,17 +958,6 @@ if test "x$silcincludes" = "xyes" -a "x$silcclient" = "xyes"; then have_silc="yes" - else - CPPFLAGS_save="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $SILC_CFLAGS" - AC_CHECK_HEADER(silcincludes.h, [silc10includes=yes]) - CPPFLAGS="$CPPFLAGS_save" - - SILC_LIBS="$SILC_LIBS -lsilc -lsilcclient -lpthread $LIBDL" - AC_CHECK_LIB(silcclient, silc_client_init, [silc10client=yes], , $SILC_LIBS) - if test "x$silc10includes" = "xyes" -a "x$silc10client" = "xyes"; then - have_silc="yes" - fi fi fi AC_SUBST(SILC_LIBS) @@ -995,20 +965,6 @@ dnl SILC Toolkit >= 1.0.1 has a new MIME API if test "x$silcclient" = "xyes"; then AC_DEFINE(HAVE_SILCMIME_H, 1, [Define if we have silcmime.h]) -elif test "x$silc10client" = "xyes"; then - CPPFLAGS_save="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $SILC_CFLAGS" - AC_MSG_CHECKING(for silcmime.h) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#include -#include - ]], [[]])], [ - AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_SILCMIME_H, 1, [Define if we have silcmime.h]) - ], [ - AC_MSG_RESULT(no) - ]) - CPPFLAGS="$CPPFLAGS_save" fi dnl ####################################################################### @@ -1123,10 +1079,7 @@ STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/bonjour//'` fi if test "x$silcincludes" != "xyes" -o "x$silcclient" != "xyes"; then - STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/silc/silc10/'` -fi -if test "x$silc10includes" != "xyes" -o "x$silc10client" != "xyes"; then - STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/silc10//'` + STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/silc//'` fi AC_SUBST(STATIC_PRPLS) STATIC_LINK_LIBS= @@ -1150,8 +1103,6 @@ else if test "x$i" = "xsilc"; then STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib${i}purple.la" - elif test "x$i" = "xsilc10"; then - STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/libsilcpurple.la" else STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib$i.la" fi @@ -1172,7 +1123,6 @@ icq) static_oscar=yes ;; sametime) static_sametime=yes ;; silc) static_silc=yes ;; - silc10) static_silc=yes ;; simple) static_simple=yes ;; yahoo) static_yahoo=yes ;; zephyr) static_zephyr=yes ;; @@ -1208,10 +1158,7 @@ DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/bonjour//'` fi if test "x$silcincludes" != "xyes" -o "x$silcclient" != "xyes"; then - DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/silc/silc10/'` -fi -if test "x$silc10includes" != "xyes" -o "x$silc10client" != "xyes"; then - DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/silc10//'` + DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/silc//'` fi AC_SUBST(DYNAMIC_PRPLS) for i in $DYNAMIC_PRPLS ; do @@ -1230,7 +1177,6 @@ icq) dynamic_oscar=yes ;; sametime) dynamic_sametime=yes ;; silc) dynamic_silc=yes ;; - silc10) dynamic_silc=yes ;; simple) dynamic_simple=yes ;; yahoo) dynamic_yahoo=yes ;; zephyr) dynamic_zephyr=yes ;; @@ -2575,7 +2521,6 @@ libpurple/protocols/oscar/Makefile libpurple/protocols/sametime/Makefile libpurple/protocols/silc/Makefile - libpurple/protocols/silc10/Makefile libpurple/protocols/simple/Makefile libpurple/protocols/yahoo/Makefile libpurple/protocols/zephyr/Makefile diff -r 0cc718e10344 -r 4f2d99bcb195 libpurple/protocols/Makefile.am --- a/libpurple/protocols/Makefile.am Mon Aug 22 06:32:44 2011 +0000 +++ b/libpurple/protocols/Makefile.am Mon Aug 22 07:01:27 2011 +0000 @@ -1,5 +1,5 @@ EXTRA_DIST = Makefile.mingw -DIST_SUBDIRS = bonjour gg irc jabber msn myspace mxit novell null oscar sametime silc silc10 simple yahoo zephyr +DIST_SUBDIRS = bonjour gg irc jabber msn myspace mxit novell null oscar sametime silc simple yahoo zephyr SUBDIRS = $(DYNAMIC_PRPLS) $(STATIC_PRPLS) diff -r 0cc718e10344 -r 4f2d99bcb195 libpurple/protocols/silc10/Makefile.am --- a/libpurple/protocols/silc10/Makefile.am Mon Aug 22 06:32:44 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -EXTRA_DIST = \ - Makefile.mingw \ - README \ - TODO - -pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION) - -SILCSOURCES = silc.c silcpurple.h buddy.c chat.c ft.c ops.c pk.c util.c wb.c wb.h - -AM_CFLAGS = $(st) - -libsilcpurple_la_LDFLAGS = -module -avoid-version - -if STATIC_SILC - -st = -DPURPLE_STATIC_PRPL $(SILC_CFLAGS) -noinst_LTLIBRARIES = libsilcpurple.la -libsilcpurple_la_SOURCES = $(SILCSOURCES) -libsilcpurple_la_CFLAGS = $(AM_CFLAGS) -libsilcpurple_la_LIBADD = $(SILC_LIBS) - -else - -st = $(SILC_CFLAGS) -pkg_LTLIBRARIES = libsilcpurple.la -libsilcpurple_la_SOURCES = $(SILCSOURCES) -libsilcpurple_la_LIBADD = $(GLIB_LIBS) $(SILC_LIBS) - -endif - -AM_CPPFLAGS = \ - -I$(top_srcdir)/libpurple \ - -I$(top_builddir)/libpurple \ - $(DEBUG_CFLAGS) \ - $(GLIB_CFLAGS) \ - $(SILC_CFLAGS) diff -r 0cc718e10344 -r 4f2d99bcb195 libpurple/protocols/silc10/Makefile.mingw --- a/libpurple/protocols/silc10/Makefile.mingw Mon Aug 22 06:32:44 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -# -# Makefile.mingw -# -# Description: Makefile for win32 (mingw) version of libsilc protocol plugin -# - -PIDGIN_TREE_TOP := ../../.. -include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak - -DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES)) - -TARGET = libsilc -NEEDED_DLLS = $(SILC_TOOLKIT)/lib/silc.dll \ - $(SILC_TOOLKIT)/lib/silcclient.dll -TYPE = PLUGIN - -# Static or Plugin... -ifeq ($(TYPE),STATIC) - DEFINES += -DSTATIC - DLL_INSTALL_DIR = $(PURPLE_INSTALL_DIR) -else -ifeq ($(TYPE),PLUGIN) - DLL_INSTALL_DIR = $(PURPLE_INSTALL_PLUGINS_DIR) -endif -endif - -## -## INCLUDE PATHS -## -INCLUDE_PATHS += -I. \ - -I$(GTK_TOP)/include \ - -I$(GTK_TOP)/include/glib-2.0 \ - -I$(GTK_TOP)/lib/glib-2.0/include \ - -I$(PURPLE_TOP) \ - -I$(PURPLE_TOP)/win32 \ - -I$(PIDGIN_TREE_TOP) \ - -I$(SILC_TOOLKIT)/include - -LIB_PATHS += -L$(GTK_TOP)/lib \ - -L$(PURPLE_TOP) \ - -L$(SILC_TOOLKIT)/lib - -## -## SOURCES, OBJECTS -## -C_SRC = silc.c \ - buddy.c \ - chat.c \ - ft.c \ - ops.c \ - pk.c \ - util.c \ - wb.c - -OBJECTS = $(C_SRC:%.c=%.o) - -## -## LIBRARIES -## -LIBS = \ - -lglib-2.0 \ - -lws2_32 \ - -lintl \ - -lpurple \ - -lsilc \ - -lsilcclient - -include $(PIDGIN_COMMON_RULES) - -## -## TARGET DEFINITIONS -## -.PHONY: all install clean - -all: $(TARGET).dll - -install: all $(DLL_INSTALL_DIR) $(PURPLE_INSTALL_DIR) - cp $(TARGET).dll $(DLL_INSTALL_DIR) - cp $(NEEDED_DLLS) $(PURPLE_INSTALL_DIR) - -$(OBJECTS): $(PURPLE_CONFIG_H) - -$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS) - $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--image-base,0x64000000 -o $(TARGET).dll - -## -## CLEAN RULES -## -clean: - rm -f $(OBJECTS) - rm -f $(TARGET).dll - -include $(PIDGIN_COMMON_TARGETS) diff -r 0cc718e10344 -r 4f2d99bcb195 libpurple/protocols/silc10/README --- a/libpurple/protocols/silc10/README Mon Aug 22 06:32:44 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 --enable-shared - 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 -r 0cc718e10344 -r 4f2d99bcb195 libpurple/protocols/silc10/TODO --- a/libpurple/protocols/silc10/TODO Mon Aug 22 06:32:44 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -Features TODO (maybe) -===================== - -Preferences - - Add joined channels to buddy list automatically (during - session) - - Add joined channels to buddy list automatically permanently - diff -r 0cc718e10344 -r 4f2d99bcb195 libpurple/protocols/silc10/buddy.c --- a/libpurple/protocols/silc10/buddy.c Mon Aug 22 06:32:44 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1748 +0,0 @@ -/* - - silcpurple_buddy.c - - Author: Pekka Riikonen - - Copyright (C) 2004 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 "silcincludes.h" -#include "silcclient.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); - -typedef struct { - char *nick; - PurpleConnection *gc; -} *SilcPurpleResolve; - -static void -silcpurple_buddy_keyagr_resolved(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context) -{ - PurpleConnection *gc = client->application; - SilcPurpleResolve r = context; - char tmp[256]; - - if (!clients) { - g_snprintf(tmp, sizeof(tmp), - _("User %s is not present in the network"), r->nick); - purple_notify_error(gc, _("Key Agreement"), - _("Cannot perform the key agreement"), tmp); - silc_free(r->nick); - silc_free(r); - return; - } - - silcpurple_buddy_keyagr_do(gc, r->nick, FALSE); - silc_free(r->nick); - silc_free(r); -} - -typedef struct { - gboolean responder; -} *SilcPurpleKeyAgr; - -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 = gc->proto_data; - SilcPurpleKeyAgr a = context; - - if (!sg->conn) - return; - - switch (status) { - case SILC_KEY_AGREEMENT_OK: - { - PurpleConversation *convo; - 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, a->responder); - silc_ske_free_key_material(key); - - - /* Open IM window */ - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - client_entry->nickname, sg->account); - if (convo) { - /* 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_conv_window_show(purple_conversation_get_window(convo)); - */ - } else { - convo = purple_conversation_new(PURPLE_CONV_TYPE_IM, sg->account, - client_entry->nickname); - } - g_snprintf(tmp, sizeof(tmp), "%s [private key]", client_entry->nickname); - purple_conversation_set_title(convo, tmp); - } - break; - - case SILC_KEY_AGREEMENT_ERROR: - purple_notify_error(gc, _("Key Agreement"), - _("Error occurred during key agreement"), NULL); - break; - - case SILC_KEY_AGREEMENT_FAILURE: - purple_notify_error(gc, _("Key Agreement"), _("Key Agreement failed"), NULL); - break; - - case SILC_KEY_AGREEMENT_TIMEOUT: - purple_notify_error(gc, _("Key Agreement"), - _("Timeout during key agreement"), NULL); - break; - - case SILC_KEY_AGREEMENT_ABORTED: - purple_notify_error(gc, _("Key Agreement"), - _("Key agreement was aborted"), NULL); - break; - - case SILC_KEY_AGREEMENT_ALREADY_STARTED: - purple_notify_error(gc, _("Key Agreement"), - _("Key agreement is already started"), NULL); - break; - - case SILC_KEY_AGREEMENT_SELF_DENIED: - purple_notify_error(gc, _("Key Agreement"), - _("Key agreement cannot be started with yourself"), - NULL); - break; - - default: - break; - } - - silc_free(a); -} - -static void -silcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name, - gboolean force_local) -{ - SilcPurple sg = gc->proto_data; - SilcClientEntry *clients; - SilcUInt32 clients_count; - char *local_ip = NULL, *remote_ip = NULL; - gboolean local = TRUE; - char *nickname; - SilcPurpleKeyAgr a; - - if (!sg->conn || !name) - return; - - if (!silc_parse_userfqdn(name, &nickname, NULL)) - return; - - /* Find client entry */ - clients = silc_client_get_clients_local(sg->client, sg->conn, nickname, name, - &clients_count); - if (!clients) { - /* Resolve unknown user */ - SilcPurpleResolve r = silc_calloc(1, sizeof(*r)); - if (!r) - return; - r->nick = g_strdup(name); - r->gc = gc; - silc_client_get_clients(sg->client, sg->conn, nickname, NULL, - silcpurple_buddy_keyagr_resolved, r); - silc_free(nickname); - return; - } - - /* 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(sg->conn->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(sg->conn->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(); - - a = silc_calloc(1, sizeof(*a)); - if (!a) - return; - a->responder = local; - - /* Send the key agreement request */ - silc_client_send_key_agreement(sg->client, sg->conn, clients[0], - local ? local_ip : NULL, NULL, 0, 60, - silcpurple_buddy_keyagr_cb, a); - - silc_free(local_ip); - silc_free(remote_ip); - silc_free(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) -{ - SilcPurpleKeyAgr ai; - SilcClientEntry client_entry; - - 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); - 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) { - ai = silc_calloc(1, sizeof(*ai)); - if (!ai) - goto out; - ai->responder = FALSE; - silc_client_perform_key_agreement(a->client, a->conn, client_entry, - a->hostname, a->port, - silcpurple_buddy_keyagr_cb, ai); - } 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: - silc_free(a->hostname); - silc_free(a); -} - -void silcpurple_buddy_keyagr_request(SilcClient client, - SilcClientConnection conn, - SilcClientEntry client_entry, - const char *hostname, SilcUInt16 port) -{ - char tmp[128], tmp2[128]; - SilcPurpleKeyAgrAsk a; - PurpleConnection *gc = client->application; - - 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 = strdup(hostname); - a->port = port; - - purple_request_action(client->application, _("Key Agreement Request"), tmp, - hostname ? tmp2 : NULL, 1, gc->account, client_entry->nickname, - NULL, 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; - - buddy = (PurpleBuddy *)node; - silcpurple_buddy_keyagr_do(buddy->account->gc, buddy->name, FALSE); -} - - -/**************************** Static IM Key **********************************/ - -static void -silcpurple_buddy_resetkey(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *b; - PurpleConnection *gc; - SilcPurple sg; - char *nickname; - SilcClientEntry *clients; - SilcUInt32 clients_count; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); - - b = (PurpleBuddy *) node; - gc = purple_account_get_connection(b->account); - sg = gc->proto_data; - - if (!silc_parse_userfqdn(b->name, &nickname, NULL)) - return; - - /* Find client entry */ - clients = silc_client_get_clients_local(sg->client, sg->conn, - nickname, b->name, - &clients_count); - if (!clients) { - silc_free(nickname); - return; - } - - clients[0]->prv_resp = FALSE; - silc_client_del_private_message_key(sg->client, sg->conn, - clients[0]); - silc_free(clients); - silc_free(nickname); -} - -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); - 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), FALSE, - client_entry->prv_resp); - if (!client_entry->prv_resp) - silc_client_send_private_message_key_request(p->client, - p->conn, - client_entry); - silc_free(p); -} - -static void -silcpurple_buddy_privkey_resolved(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - 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); - g_free(context); - return; - } - - silcpurple_buddy_privkey(client->application, context); - silc_free(context); -} - -static void -silcpurple_buddy_privkey(PurpleConnection *gc, const char *name) -{ - SilcPurple sg = gc->proto_data; - char *nickname; - SilcPurplePrivkey p; - SilcClientEntry *clients; - SilcUInt32 clients_count; - - if (!name) - return; - if (!silc_parse_userfqdn(name, &nickname, NULL)) - return; - - /* Find client entry */ - clients = silc_client_get_clients_local(sg->client, sg->conn, - nickname, name, - &clients_count); - if (!clients) { - silc_client_get_clients(sg->client, sg->conn, nickname, NULL, - silcpurple_buddy_privkey_resolved, - g_strdup(name)); - silc_free(nickname); - return; - } - - p = silc_calloc(1, sizeof(*p)); - if (!p) - return; - p->client = sg->client; - p->conn = sg->conn; - p->client_id = *clients[0]->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), - gc->account, NULL, NULL, p); - - silc_free(clients); - silc_free(nickname); -} - -static void -silcpurple_buddy_privkey_menu(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *buddy; - PurpleConnection *gc; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); - - buddy = (PurpleBuddy *) node; - gc = purple_account_get_connection(buddy->account); - - silcpurple_buddy_privkey(gc, buddy->name); -} - - -/**************************** Get Public Key *********************************/ - -typedef struct { - SilcClient client; - SilcClientConnection conn; - SilcClientID client_id; -} *SilcPurpleBuddyGetkey; - -static void -silcpurple_buddy_getkey(PurpleConnection *gc, const char *name); - -static void -silcpurple_buddy_getkey_cb(SilcPurpleBuddyGetkey g, - SilcClientCommandReplyContext cmd) -{ - SilcClientEntry client_entry; - unsigned char *pk; - SilcUInt32 pk_len; - - /* 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); - silc_free(g); - return; - } - - if (!client_entry->public_key) { - silc_free(g); - return; - } - - /* Now verify the public key */ - pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len); - silcpurple_verify_public_key(g->client, g->conn, client_entry->nickname, - SILC_SOCKET_TYPE_CLIENT, - pk, pk_len, SILC_SKE_PK_TYPE_SILC, - NULL, NULL); - silc_free(pk); - silc_free(g); -} - -static void -silcpurple_buddy_getkey_resolved(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - 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); - g_free(context); - return; - } - - silcpurple_buddy_getkey(client->application, context); - silc_free(context); -} - -static void -silcpurple_buddy_getkey(PurpleConnection *gc, const char *name) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcClientEntry *clients; - SilcUInt32 clients_count; - SilcPurpleBuddyGetkey g; - char *nickname; - - if (!name) - return; - - if (!silc_parse_userfqdn(name, &nickname, NULL)) - return; - - /* Find client entry */ - clients = silc_client_get_clients_local(client, conn, nickname, name, - &clients_count); - if (!clients) { - silc_client_get_clients(client, conn, nickname, NULL, - silcpurple_buddy_getkey_resolved, - g_strdup(name)); - silc_free(nickname); - return; - } - - /* Call GETKEY */ - g = silc_calloc(1, sizeof(*g)); - if (!g) - return; - g->client = client; - g->conn = conn; - g->client_id = *clients[0]->id; - silc_client_command_call(client, conn, NULL, "GETKEY", - clients[0]->nickname, NULL); - silc_client_command_pending(conn, SILC_COMMAND_GETKEY, - conn->cmd_ident, - (SilcCommandCb)silcpurple_buddy_getkey_cb, g); - silc_free(clients); - silc_free(nickname); -} - -static void -silcpurple_buddy_getkey_menu(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *buddy; - PurpleConnection *gc; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); - - buddy = (PurpleBuddy *) node; - gc = purple_account_get_connection(buddy->account); - - silcpurple_buddy_getkey(gc, buddy->name); -} - -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_BLIST_NODE_IS_BUDDY(node)); - - b = (PurpleBuddy *) node; - gc = purple_account_get_connection(b->account); - sg = gc->proto_data; - - pkfile = purple_blist_node_get_string(node, "public-key"); - if (!silc_pkcs_load_public_key(pkfile, &public_key, SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(pkfile, &public_key, SILC_PKCS_FILE_BIN)) { - purple_notify_error(gc, - _("Show Public Key"), - _("Could not load public key"), NULL); - return; - } - - silcpurple_show_public_key(sg, b->name, 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; - 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, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context); - -void silcpurple_get_info(PurpleConnection *gc, const char *who) -{ - SilcPurple sg = gc->proto_data; - 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_find_buddy(gc->account, nick); - if (b) { - /* 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) { - /* 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 (!b->proto_data) { - g_snprintf(tmp, sizeof(tmp), - _("User %s is not present in the network"), b->name); - purple_notify_error(gc, _("User Information"), - _("Cannot get user information"), tmp); - return; - } - - client_entry = silc_client_get_client_by_id(client, conn, b->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"), - r->b->name); - 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_prpl_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(bool success, void *context) -{ - SilcPurpleBuddyRes r = context; - PurpleBuddy *b = r->b; - SilcClient client = r->client; - SilcClientEntry client_entry; - SilcAttributePayload attr; - SilcAttribute attribute; - SilcVCardStruct vcard; - SilcAttributeObjMime message, extension; -#ifdef SILC_ATTRIBUTE_USER_ICON - SilcAttributeObjMime usericon; -#endif - SilcAttributeObjPk serverpk, usersign, serversign; - gboolean usign_success = TRUE, ssign_success = TRUE; - char filename[512], filename2[512], *fingerprint = NULL, *tmp; - SilcUInt32 len; - int i; - - if (!success) { - /* The user did not trust the public key. */ - silcpurple_add_buddy_pk_no(r); - 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_prpl_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); - 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); - return; - } - - memset(&vcard, 0, sizeof(vcard)); - memset(&message, 0, sizeof(message)); - memset(&extension, 0, sizeof(extension)); -#ifdef SILC_ATTRIBUTE_USER_ICON - memset(&usericon, 0, sizeof(usericon)); -#endif - 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: - if (!silc_attribute_get_object(attr, (void *)&message, - sizeof(message))) - continue; - break; - - case SILC_ATTRIBUTE_EXTENSION: - if (!silc_attribute_get_object(attr, (void *)&extension, - sizeof(extension))) - continue; - break; - -#ifdef SILC_ATTRIBUTE_USER_ICON - case SILC_ATTRIBUTE_USER_ICON: - if (!silc_attribute_get_object(attr, (void *)&usericon, - sizeof(usericon))) - continue; - break; -#endif - - 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 */ - - if (usersign.data) { - SilcPKCS pkcs; - unsigned char *verifyd; - SilcUInt32 verify_len; - - silc_pkcs_alloc((unsigned char*)"rsa", &pkcs); - verifyd = silc_attribute_get_verify_data(client_entry->attrs, - FALSE, &verify_len); - if (verifyd && silc_pkcs_public_key_set(pkcs, client_entry->public_key)){ - if (!silc_pkcs_verify_with_hash(pkcs, client->sha1hash, - usersign.data, - usersign.data_len, - verifyd, verify_len)) - usign_success = FALSE; - } - silc_free(verifyd); - } - - if (serversign.data && !strcmp(serverpk.type, "silc-rsa")) { - SilcPublicKey public_key; - SilcPKCS pkcs; - unsigned char *verifyd; - SilcUInt32 verify_len; - - if (silc_pkcs_public_key_decode(serverpk.data, serverpk.data_len, - &public_key)) { - silc_pkcs_alloc((unsigned char *)"rsa", &pkcs); - verifyd = silc_attribute_get_verify_data(client_entry->attrs, - TRUE, &verify_len); - if (verifyd && silc_pkcs_public_key_set(pkcs, public_key)) { - if (!silc_pkcs_verify_with_hash(pkcs, client->sha1hash, - serversign.data, - serversign.data_len, - verifyd, verify_len)) - ssign_success = FALSE; - } - silc_pkcs_public_key_free(public_key); - silc_free(verifyd); - } - } - - fingerprint = silc_fingerprint(client_entry->fingerprint, - client_entry->fingerprint_len); - for (i = 0; i < strlen(fingerprint); i++) - if (fingerprint[i] == ' ') - fingerprint[i] = '_'; - - if (usign_success || ssign_success) { - struct passwd *pw; - struct stat st; - - 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 ((g_stat(filename, &st)) == -1) { - if (errno == ENOENT) { - if (pw->pw_uid == geteuid()) { - int ret = g_mkdir(filename, 0755); - if (ret < 0) - 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.mime) { - memset(filename2, 0, sizeof(filename2)); - g_snprintf(filename2, sizeof(filename2) - 1, - "%s" G_DIR_SEPARATOR_S "status_message.mime", - filename); - silc_file_writefile(filename2, (char *)message.mime, - message.mime_len); - } - - /* Save extension data */ - if (extension.mime) { - memset(filename2, 0, sizeof(filename2)); - g_snprintf(filename2, sizeof(filename2) - 1, - "%s" G_DIR_SEPARATOR_S "extension.mime", - filename); - silc_file_writefile(filename2, (char *)extension.mime, - extension.mime_len); - } - -#ifdef SILC_ATTRIBUTE_USER_ICON - /* Save user icon */ - if (usericon.mime) { - SilcMime m = silc_mime_decode(usericon.mime, - usericon.mime_len); - if (m) { - const char *type = silc_mime_get_field(m, "Content-Type"); - if (!strcmp(type, "image/jpeg") || - !strcmp(type, "image/gif") || - !strcmp(type, "image/bmp") || - !strcmp(type, "image/png")) { - const unsigned char *data; - SilcUInt32 data_len; - data = silc_mime_get_data(m, &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_memdup(data, data_len), data_len, NULL); - } - } - silc_mime_free(m); - } - } -#endif - } - - /* 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_prpl_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_free(fingerprint); - silc_free(r); -} - -static void -silcpurple_add_buddy_ask_import(void *user_data, const char *name) -{ - SilcPurpleBuddyRes r = (SilcPurpleBuddyRes)user_data; - SilcPublicKey public_key; - - /* Load the public key */ - if (!silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_BIN)) { - silcpurple_add_buddy_ask_pk_cb(r, 0); - purple_notify_error(r->client->application, - _("Add Buddy"), _("Could not load public key"), NULL); - return; - } - - /* Now verify the public key */ - r->offline_pk = silc_pkcs_public_key_encode(public_key, &r->offline_pk_len); - silcpurple_verify_public_key(r->client, r->conn, r->b->name, - SILC_SOCKET_TYPE_CLIENT, - r->offline_pk, r->offline_pk_len, - SILC_SKE_PK_TYPE_SILC, - 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_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, 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"), - r->b->name); - 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_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r, 2, - _("Cancel"), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb), - _("_Import..."), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb)); -} - -static void -silcpurple_add_buddy_getkey_cb(SilcPurpleBuddyRes r, - SilcClientCommandReplyContext cmd) -{ - SilcClientEntry client_entry; - unsigned char *pk; - SilcUInt32 pk_len; - - /* 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; - } - - /* Now verify the public key */ - pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len); - silcpurple_verify_public_key(r->client, r->conn, client_entry->nickname, - SILC_SOCKET_TYPE_CLIENT, - pk, pk_len, SILC_SKE_PK_TYPE_SILC, - silcpurple_add_buddy_save, r); - silc_free(pk); -} - -static void -silcpurple_add_buddy_select_cb(SilcPurpleBuddyRes r, PurpleRequestFields *fields) -{ - PurpleRequestField *f; - GList *list; - SilcClientEntry client_entry; - - 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); - silcpurple_add_buddy_resolved(r->client, r->conn, &client_entry, 1, r); -} - -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, - SilcClientEntry *clients, - SilcUInt32 clients_count) -{ - PurpleRequestFields *fields; - PurpleRequestFieldGroup *g; - PurpleRequestField *f; - char tmp[512], tmp2[128]; - int i; - char *fingerprint; - - 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); - - for (i = 0; i < clients_count; i++) { - fingerprint = NULL; - if (clients[i]->fingerprint) { - fingerprint = silc_fingerprint(clients[i]->fingerprint, - clients[i]->fingerprint_len); - g_snprintf(tmp2, sizeof(tmp2), "\n%s", fingerprint); - } - g_snprintf(tmp, sizeof(tmp), "%s - %s (%s@%s)%s", - clients[i]->realname, clients[i]->nickname, - clients[i]->username, clients[i]->hostname ? - clients[i]->hostname : "", - fingerprint ? tmp2 : ""); - purple_request_field_list_add_icon(f, tmp, NULL, clients[i]); - 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_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r); -} - -static void -silcpurple_add_buddy_resolved(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context) -{ - SilcPurpleBuddyRes r = context; - PurpleBuddy *b = r->b; - SilcAttributePayload pub; - SilcAttributeObjPk userpk; - unsigned char *pk; - SilcUInt32 pk_len; - const char *filename; - - 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_count) { - 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 (clients_count > 1 && !r->pubkey_search) { - if (r->init) { - silc_free(r); - return; - } - - silcpurple_add_buddy_select(r, clients, clients_count); - return; - } - - /* If we searched using public keys and more than one entry was found - the same person is logged on multiple times. */ - if (clients_count > 1 && r->pubkey_search && b->name) { - if (r->init) { - /* Find the entry that closest matches to the - buddy nickname. */ - int i; - for (i = 0; i < clients_count; i++) { - if (!g_ascii_strncasecmp(b->name, clients[i]->nickname, - strlen(b->name))) { - clients[0] = clients[i]; - break; - } - } - } else { - /* Verify from user which one is correct */ - silcpurple_add_buddy_select(r, clients, clients_count); - return; - } - } - - /* The client was found. Now get its public key and verify - that before adding the buddy. */ - memset(&userpk, 0, sizeof(userpk)); - b->proto_data = silc_memdup(clients[0]->id, sizeof(*clients[0]->id)); - r->client_id = *clients[0]->id; - - /* Get the public key from attributes, if not present then - resolve it with GETKEY unless we have it cached already. */ - if (clients[0]->attrs && !clients[0]->public_key) { - pub = silcpurple_get_attr(clients[0]->attrs, - SILC_ATTRIBUTE_USER_PUBLIC_KEY); - if (!pub || !silc_attribute_get_object(pub, (void *)&userpk, - sizeof(userpk))) { - /* Get public key with GETKEY */ - silc_client_command_call(client, conn, NULL, - "GETKEY", clients[0]->nickname, NULL); - silc_client_command_pending(conn, SILC_COMMAND_GETKEY, - conn->cmd_ident, - (SilcCommandCb)silcpurple_add_buddy_getkey_cb, - r); - return; - } - if (!silc_pkcs_public_key_decode(userpk.data, userpk.data_len, - &clients[0]->public_key)) - return; - silc_free(userpk.data); - } else if (filename && !clients[0]->public_key) { - if (!silc_pkcs_load_public_key(filename, &clients[0]->public_key, - SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(filename, &clients[0]->public_key, - SILC_PKCS_FILE_BIN)) { - /* Get public key with GETKEY */ - silc_client_command_call(client, conn, NULL, - "GETKEY", clients[0]->nickname, NULL); - silc_client_command_pending(conn, SILC_COMMAND_GETKEY, - conn->cmd_ident, - (SilcCommandCb)silcpurple_add_buddy_getkey_cb, - r); - return; - } - } else if (!clients[0]->public_key) { - /* Get public key with GETKEY */ - silc_client_command_call(client, conn, NULL, - "GETKEY", clients[0]->nickname, NULL); - silc_client_command_pending(conn, SILC_COMMAND_GETKEY, - conn->cmd_ident, - (SilcCommandCb)silcpurple_add_buddy_getkey_cb, - r); - return; - } - - /* We have the public key, verify it. */ - pk = silc_pkcs_public_key_encode(clients[0]->public_key, &pk_len); - silcpurple_verify_public_key(client, conn, clients[0]->nickname, - SILC_SOCKET_TYPE_CLIENT, - pk, pk_len, SILC_SKE_PK_TYPE_SILC, - silcpurple_add_buddy_save, r); - silc_free(pk); -} - -static void -silcpurple_add_buddy_i(PurpleConnection *gc, PurpleBuddy *b, gboolean init) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcPurpleBuddyRes r; - SilcBuffer attrs; - const char *filename, *name = b->name; - - 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, - SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(filename, &public_key, - SILC_PKCS_FILE_BIN)) - 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, -#ifdef SILC_ATTRIBUTE_USER_ICON - SILC_ATTRIBUTE_USER_ICON, -#endif - 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(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) -{ - /* Don't add if the buddy is already on the list. - * - * SILC doesn't have groups, so we 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) -{ - PurpleBuddyList *blist; - PurpleBlistNode *gnode, *cnode, *bnode; - PurpleBuddy *buddy; - PurpleAccount *account; - - account = purple_connection_get_account(gc); - - if ((blist = purple_get_blist()) != NULL) - { - for (gnode = blist->root; gnode != NULL; gnode = gnode->next) - { - if (!PURPLE_BLIST_NODE_IS_GROUP(gnode)) - continue; - for (cnode = gnode->child; cnode != NULL; cnode = cnode->next) - { - if (!PURPLE_BLIST_NODE_IS_CONTACT(cnode)) - continue; - for (bnode = cnode->child; bnode != NULL; bnode = bnode->next) - { - if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) - continue; - buddy = (PurpleBuddy *)bnode; - if (purple_buddy_get_account(buddy) == account) - silcpurple_add_buddy_i(gc, buddy, TRUE); - } - } - } - } -} - -void silcpurple_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, - PurpleGroup *group) -{ - silc_free(buddy->proto_data); -} - -void silcpurple_idle_set(PurpleConnection *gc, int idle) - -{ - SilcPurple sg; - SilcClient client; - SilcClientConnection conn; - SilcAttributeObjService service; - const char *server; - int port; - - sg = gc->proto_data; - 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(PurpleBuddy *b) -{ - SilcPurple sg = b->account->gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcClientID *client_id = b->proto_data; - 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(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) -{ - SilcPurple sg = b->account->gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcClientID *client_id = b->proto_data; - 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; - - if (client_entry->nickname) - purple_notify_user_info_add_pair(user_info, _("Nickname"), - client_entry->nickname); - if (client_entry->username && client_entry->hostname) { - g_snprintf(tmp, sizeof(tmp), "%s@%s", client_entry->username, client_entry->hostname); - purple_notify_user_info_add_pair(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(user_info, _("User Modes"), tmp); - } - - silcpurple_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr); - - if (statusstr) { - purple_notify_user_info_add_pair(user_info, _("Message"), statusstr); - g_free(statusstr); - } - - if (full) { - if (moodstr) { - purple_notify_user_info_add_pair(user_info, _("Mood"), moodstr); - g_free(moodstr); - } - - if (contactstr) { - purple_notify_user_info_add_pair(user_info, _("Preferred Contact"), contactstr); - g_free(contactstr); - } - - if (langstr) { - purple_notify_user_info_add_pair(user_info, _("Preferred Language"), langstr); - g_free(langstr); - } - - if (devicestr) { - purple_notify_user_info_add_pair(user_info, _("Device"), devicestr); - g_free(devicestr); - } - - if (tzstr) { - purple_notify_user_info_add_pair(user_info, _("Timezone"), tzstr); - g_free(tzstr); - } - - if (geostr) { - purple_notify_user_info_add_pair(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_BLIST_NODE_IS_BUDDY(node)); - - b = (PurpleBuddy *) node; - gc = purple_account_get_connection(b->account); - sg = gc->proto_data; - - /* Call KILL */ - silc_client_command_call(sg->client, sg->conn, NULL, "KILL", - b->name, "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) -{ - PurpleConnection *gc = purple_account_get_connection(buddy->account); - SilcPurple sg = gc->proto_data; - SilcClientConnection conn = sg->conn; - const char *pkfile = NULL; - SilcClientEntry client_entry = NULL; - PurpleMenuAction *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, - buddy->proto_data); - - if (client_entry && client_entry->send_key) { - act = purple_menu_action_new(_("Reset IM Key"), - PURPLE_CALLBACK(silcpurple_buddy_resetkey), - NULL, NULL); - m = g_list_append(m, act); - - } else { - act = purple_menu_action_new(_("IM with Key Exchange"), - PURPLE_CALLBACK(silcpurple_buddy_keyagr), - NULL, NULL); - m = g_list_append(m, act); - - act = purple_menu_action_new(_("IM with Password"), - PURPLE_CALLBACK(silcpurple_buddy_privkey_menu), - NULL, NULL); - m = g_list_append(m, act); - } - - if (pkfile) { - act = purple_menu_action_new(_("Show Public Key"), - PURPLE_CALLBACK(silcpurple_buddy_showkey), - NULL, NULL); - m = g_list_append(m, act); - - } else { - act = purple_menu_action_new(_("Get Public Key..."), - PURPLE_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_menu_action_new(_("Kill User"), - PURPLE_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_menu_action_new(_("Draw On Whiteboard"), - PURPLE_CALLBACK(silcpurple_buddy_wb), - (void *)wb, NULL); - m = g_list_append(m, act); - } - return m; -} - -#ifdef SILC_ATTRIBUTE_USER_ICON -void silcpurple_buddy_set_icon(PurpleConnection *gc, PurpleStoredImage *img) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcMime mime; - char type[32]; - unsigned char *icon; - const char *t; - SilcAttributeObjMime obj; - - /* Remove */ - if (!img) { - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_USER_ICON, NULL); - return; - } - - /* Add */ - mime = silc_mime_alloc(); - if (!mime) - return; - - t = purple_imgstore_get_extension(img); - if (!t || !strcmp(t, "icon")) { - silc_mime_free(mime); - return; - } - if (!strcmp(t, "jpg")) - t = "jpeg"; - g_snprintf(type, sizeof(type), "image/%s", t); - silc_mime_add_field(mime, "Content-Type", type); - silc_mime_add_data(mime, purple_imgstore_get_data(img), purple_imgstore_get_size(img)); - - obj.mime = icon = silc_mime_encode(mime, &obj.mime_len); - if (obj.mime) - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_USER_ICON, &obj, sizeof(obj)); - - silc_free(icon); - silc_mime_free(mime); -} -#endif diff -r 0cc718e10344 -r 4f2d99bcb195 libpurple/protocols/silc10/chat.c --- a/libpurple/protocols/silc10/chat.c Mon Aug 22 06:32:44 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1456 +0,0 @@ -/* - - silcpurple_chat.c - - Author: Pekka Riikonen - - Copyright (C) 2004 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 "silcincludes.h" -#include "silcclient.h" -#include "silcpurple.h" -#include "wb.h" - -/***************************** Channel Routines ******************************/ - -GList *silcpurple_chat_info(PurpleConnection *gc) -{ - GList *ci = NULL; - struct proto_chat_entry *pce; - - pce = g_new0(struct proto_chat_entry, 1); - pce->label = _("_Channel:"); - pce->identifier = "channel"; - pce->required = TRUE; - ci = g_list_append(ci, pce); - - pce = g_new0(struct proto_chat_entry, 1); - pce->label = _("_Passphrase:"); - pce->identifier = "passphrase"; - pce->secret = TRUE; - ci = g_list_append(ci, pce); - - return ci; -} - -GHashTable *silcpurple_chat_info_defaults(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, - SilcChannelEntry *channels, - SilcUInt32 channels_count, - 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); - return; - } - - silcpurple_chat_getinfo(gc, components); -} - - -static void -silcpurple_chat_getinfo(PurpleConnection *gc, GHashTable *components) -{ - SilcPurple sg = gc->proto_data; - const char *chname; - char *buf, 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, _("Channel Name: %s"), tmp2); - g_free(tmp2); - if (channel->user_list && silc_hash_table_count(channel->user_list)) - g_string_append_printf(s, _("
User Count: %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, _("
Channel Founder: %s"), - tmp2); - g_free(tmp2); - break; - } - } - silc_hash_table_list_reset(&htl); - - if (channel->channel_key) - g_string_append_printf(s, _("
Channel Cipher: %s"), - silc_cipher_get_name(channel->channel_key)); - if (channel->hmac) - /* Definition of HMAC: http://en.wikipedia.org/wiki/HMAC */ - g_string_append_printf(s, _("
Channel HMAC: %s"), - silc_hmac_get_name(channel->hmac)); - - if (channel->topic) { - tmp2 = g_markup_escape_text(channel->topic, -1); - g_string_append_printf(s, _("
Channel Topic:
%s"), tmp2); - g_free(tmp2); - } - - if (channel->mode) { - g_string_append_printf(s, _("
Channel Modes: ")); - 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); - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - - g_string_append_printf(s, _("
Founder Key Fingerprint:
%s"), fingerprint); - g_string_append_printf(s, _("
Founder Key Babbleprint:
%s"), babbleprint); - - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); - } - - buf = g_string_free(s, FALSE); - purple_notify_formatted(gc, NULL, _("Channel Information"), NULL, buf, NULL, NULL); - g_free(buf); -} - - -static void -silcpurple_chat_getinfo_menu(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat = (PurpleChat *)node; - silcpurple_chat_getinfo(chat->account->gc, chat->components); -} - - -#if 0 /* XXX For now these are not implemented. We need better - listview dialog from Purple for these. */ -/************************** Channel Invite List ******************************/ - -static void -silcpurple_chat_invitelist(PurpleBlistNode *node, gpointer data); -{ - -} - - -/**************************** Channel Ban List *******************************/ - -static void -silcpurple_chat_banlist(PurpleBlistNode *node, gpointer data); -{ - -} -#endif - - -/************************* Channel Authentication ****************************/ - -typedef struct { - SilcPurple sg; - SilcChannelEntry channel; - PurpleChat *c; - SilcBuffer 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, SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_BIN)) { - silcpurple_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys); - silc_buffer_free(sgc->pubkeys); - silc_free(sgc); - purple_notify_error(client->application, - _("Add Channel Public Key"), - _("Could not load public key"), NULL); - return; - } - - pk = silc_pkcs_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, - pk->len, 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, - ++conn->cmd_ident, 3, - 1, chidp->data, chidp->len, - 2, mode, sizeof(mode), - 9, chpks->data, chpks->len); - silc_buffer_free(chpks); - silc_buffer_free(chidp); - silc_buffer_free(sgc->pubkeys); - silc_free(sgc); -} - -static void -silcpurple_chat_chpk_cancel(void *user_data, const char *name) -{ - SilcPurpleChauth sgc = (SilcPurpleChauth)user_data; - silcpurple_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys); - silc_buffer_free(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_connection_get_account(sg->gc), NULL, NULL, sgc); - return; - } - - list = purple_request_field_list_get_items(f); - chpks = silc_buffer_alloc_size(2); - - for (ct = 0; list; list = list->next, ct++) { - public_key = purple_request_field_list_get_data(f, list->data); - if (purple_request_field_list_is_selected(f, list->data)) { - /* Delete this public key */ - pk = silc_pkcs_public_key_payload_encode(public_key); - chpks = silc_argument_payload_encode_one(chpks, pk->data, - pk->len, 0x01); - silc_buffer_free(pk); - c++; - } - silc_pkcs_public_key_free(public_key); - } - 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, - ++conn->cmd_ident, 3, - 1, chidp->data, chidp->len, - 2, mode, sizeof(mode), - 9, chpks->data, chpks->len); - silc_buffer_free(chpks); - silc_buffer_free(chidp); - silc_buffer_free(sgc->pubkeys); - silc_free(sgc); -} - -static void -silcpurple_chat_chauth_ok(SilcPurpleChauth sgc, PurpleRequestFields *fields) -{ - SilcPurple sg = sgc->sg; - PurpleRequestField *f; - 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 && strcmp(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"); - } - - silc_buffer_free(sgc->pubkeys); - silc_free(sgc); -} - -void silcpurple_chat_chauth_show(SilcPurple sg, SilcChannelEntry channel, - SilcBuffer channel_pubkeys) -{ - SilcUInt16 argc; - SilcArgumentPayload chpks; - unsigned char *pk; - SilcUInt32 pk_len, type; - char *fingerprint, *babbleprint; - SilcPublicKey pubkey; - SilcPublicKeyIdentifier ident; - char tmp2[1024], t[512]; - 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); - - g_snprintf(t, sizeof(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) { - 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_connection_get_account(sg->gc), NULL, NULL, sgc); - return; - } - sgc->pubkeys = silc_buffer_copy(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_GET16_MSB(argc, channel_pubkeys->data); - chpks = silc_argument_payload_parse(channel_pubkeys->data + 2, - channel_pubkeys->len - 2, argc); - if (!chpks) - return; - - pk = silc_argument_get_first_arg(chpks, &type, &pk_len); - while (pk) { - fingerprint = silc_hash_fingerprint(NULL, pk + 4, pk_len - 4); - babbleprint = silc_hash_babbleprint(NULL, pk + 4, pk_len - 4); - silc_pkcs_public_key_payload_decode(pk, pk_len, &pubkey); - ident = silc_pkcs_decode_identifier(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, pubkey); - - silc_free(fingerprint); - silc_free(babbleprint); - silc_pkcs_free_identifier(ident); - pk = silc_argument_get_next_arg(chpks, &type, &pk_len); - } - - 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_connection_get_account(sg->gc), NULL, NULL, sgc); - - silc_argument_payload_free(chpks); -} - -static void -silcpurple_chat_chauth(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "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; - char tmp[512]; - 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 */ - g_snprintf(tmp, sizeof(tmp), "%s [Private Group]", name); - comp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); - g_hash_table_replace(comp, g_strdup("channel"), g_strdup(tmp)); - g_hash_table_replace(comp, g_strdup("passphrase"), g_strdup(passphrase)); - - cn = purple_chat_new(sg->account, alias, comp); - g = (PurpleGroup *)p->c->node.parent; - 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(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_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - p = silc_calloc(1, sizeof(*p)); - if (!p) - return; - p->sg = sg; - - p->channel = g_hash_table_lookup(chat->components, "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_connection_get_account(gc), NULL, NULL, p); -} - - -/****************************** Channel Modes ********************************/ - -static void -silcpurple_chat_permanent_reset(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "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_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - 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(chat->components, "channel"); - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", channel, - "+f", NULL); -} - -typedef struct { - SilcPurple sg; - char *channel; -} *SilcPurpleChatInput; - -static void -silcpurple_chat_ulimit_cb(SilcPurpleChatInput s, const char *limit) -{ - SilcChannelEntry channel; - int ulimit = 0; - - channel = silc_client_get_channel(s->sg->client, s->sg->conn, - (char *)s->channel); - if (!channel) - return; - if (limit) - ulimit = atoi(limit); - - if (!limit || !(*limit) || *limit == '0') { - if (limit && ulimit == channel->user_limit) { - silc_free(s); - return; - } - silc_client_command_call(s->sg->client, s->sg->conn, NULL, "CMODE", - s->channel, "-l", NULL); - - silc_free(s); - return; - } - - if (ulimit == channel->user_limit) { - silc_free(s); - return; - } - - /* Call CMODE */ - silc_client_command_call(s->sg->client, s->sg->conn, NULL, "CMODE", - s->channel, "+l", limit, NULL); - - silc_free(s); -} - -static void -silcpurple_chat_ulimit(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - SilcPurpleChatInput s; - SilcChannelEntry channel; - char *ch; - char tmp[32]; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - if (!sg->conn) - return; - - ch = g_strdup(g_hash_table_lookup(chat->components, "channel")); - channel = silc_client_get_channel(sg->client, sg->conn, (char *)ch); - if (!channel) - return; - - s = silc_calloc(1, sizeof(*s)); - if (!s) - return; - s->channel = ch; - s->sg = 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_connection_get_account(gc), NULL, NULL, s); -} - -static void -silcpurple_chat_resettopic(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "channel"), - "-t", NULL); -} - -static void -silcpurple_chat_settopic(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "channel"), - "+t", NULL); -} - -static void -silcpurple_chat_resetprivate(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "channel"), - "-p", NULL); -} - -static void -silcpurple_chat_setprivate(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "channel"), - "+p", NULL); -} - -static void -silcpurple_chat_resetsecret(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "channel"), - "-s", NULL); -} - -static void -silcpurple_chat_setsecret(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "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 = chat->components; - PurpleConnection *gc = purple_account_get_connection(chat->account); - SilcPurple sg = gc->proto_data; - SilcClientConnection conn = sg->conn; - const char *chname = NULL; - SilcChannelEntry channel = NULL; - SilcChannelUser chu = NULL; - SilcUInt32 mode = 0; - - GList *m = NULL; - PurpleMenuAction *act; - - if (components) - chname = g_hash_table_lookup(components, "channel"); - if (chname) - 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_menu_action_new(_("Get Info"), - PURPLE_CALLBACK(silcpurple_chat_getinfo_menu), - NULL, NULL); - m = g_list_append(m, act); - -#if 0 /* XXX For now these are not implemented. We need better - listview dialog from Purple for these. */ - if (mode & SILC_CHANNEL_UMODE_CHANOP) { - act = purple_menu_action_new(_("Invite List"), - PURPLE_CALLBACK(silcpurple_chat_invitelist), - NULL, NULL); - m = g_list_append(m, act); - - act = purple_menu_action_new(_("Ban List"), - PURPLE_CALLBACK(silcpurple_chat_banlist), - NULL, NULL); - m = g_list_append(m, act); - } -#endif - - if (chu) { - act = purple_menu_action_new(_("Add Private Group"), - PURPLE_CALLBACK(silcpurple_chat_prv), - NULL, NULL); - m = g_list_append(m, act); - } - - if (mode & SILC_CHANNEL_UMODE_CHANFO) { - act = purple_menu_action_new(_("Channel Authentication"), - PURPLE_CALLBACK(silcpurple_chat_chauth), - NULL, NULL); - m = g_list_append(m, act); - - if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) { - act = purple_menu_action_new(_("Reset Permanent"), - PURPLE_CALLBACK(silcpurple_chat_permanent_reset), - NULL, NULL); - m = g_list_append(m, act); - } else { - act = purple_menu_action_new(_("Set Permanent"), - PURPLE_CALLBACK(silcpurple_chat_permanent), - NULL, NULL); - m = g_list_append(m, act); - } - } - - if (mode & SILC_CHANNEL_UMODE_CHANOP) { - act = purple_menu_action_new(_("Set User Limit"), - PURPLE_CALLBACK(silcpurple_chat_ulimit), - NULL, NULL); - m = g_list_append(m, act); - - if (channel->mode & SILC_CHANNEL_MODE_TOPIC) { - act = purple_menu_action_new(_("Reset Topic Restriction"), - PURPLE_CALLBACK(silcpurple_chat_resettopic), - NULL, NULL); - m = g_list_append(m, act); - } else { - act = purple_menu_action_new(_("Set Topic Restriction"), - PURPLE_CALLBACK(silcpurple_chat_settopic), - NULL, NULL); - m = g_list_append(m, act); - } - - if (channel->mode & SILC_CHANNEL_MODE_PRIVATE) { - act = purple_menu_action_new(_("Reset Private Channel"), - PURPLE_CALLBACK(silcpurple_chat_resetprivate), - NULL, NULL); - m = g_list_append(m, act); - } else { - act = purple_menu_action_new(_("Set Private Channel"), - PURPLE_CALLBACK(silcpurple_chat_setprivate), - NULL, NULL); - m = g_list_append(m, act); - } - - if (channel->mode & SILC_CHANNEL_MODE_SECRET) { - act = purple_menu_action_new(_("Reset Secret Channel"), - PURPLE_CALLBACK(silcpurple_chat_resetsecret), - NULL, NULL); - m = g_list_append(m, act); - } else { - act = purple_menu_action_new(_("Set Secret Channel"), - PURPLE_CALLBACK(silcpurple_chat_setsecret), - NULL, NULL); - m = g_list_append(m, act); - } - } - - if (channel) { - SilcPurpleChatWb wb; - wb = silc_calloc(1, sizeof(*wb)); - wb->sg = sg; - wb->channel = channel; - act = purple_menu_action_new(_("Draw On Whiteboard"), - PURPLE_CALLBACK(silcpurple_chat_wb), - (void *)wb, NULL); - m = g_list_append(m, act); - } - - return m; -} - - -/******************************* Joining Etc. ********************************/ - -void silcpurple_chat_join_done(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - SilcChannelEntry channel = context; - PurpleConversation *convo; - SilcUInt32 retry = SILC_PTR_TO_32(channel->context); - SilcHashTableList htl; - SilcChannelUser chu; - GList *users = NULL, *flags = NULL; - char tmp[256]; - - if (!clients && retry < 1) { - /* Resolving users failed, try again. */ - channel->context = SILC_32_TO_PTR(retry + 1); - silc_client_get_clients_by_channel(client, conn, channel, - silcpurple_chat_join_done, channel); - return; - } - - /* Add channel to Purple */ - channel->context = SILC_32_TO_PTR(++sg->channel_ids); - serv_got_joined_chat(gc, sg->channel_ids, channel->channel_name); - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - return; - - /* Add all users to channel */ - silc_hash_table_list(channel->user_list, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - PurpleConvChatBuddyFlags f = PURPLE_CBFLAGS_NONE; - if (!chu->client->nickname) - continue; - chu->context = SILC_32_TO_PTR(sg->channel_ids); - - if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) - f |= PURPLE_CBFLAGS_FOUNDER; - if (chu->mode & SILC_CHANNEL_UMODE_CHANOP) - f |= PURPLE_CBFLAGS_OP; - users = g_list_append(users, g_strdup(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 %s"), - channel->channel_name); - else - g_snprintf(tmp, sizeof(tmp), - _("Channel founder on %s is %s"), - channel->channel_name, chu->client->nickname); - - purple_conversation_write(convo, NULL, tmp, - PURPLE_MESSAGE_SYSTEM, time(NULL)); - - } - } - silc_hash_table_list_reset(&htl); - - purple_conv_chat_add_users(PURPLE_CONV_CHAT(convo), users, NULL, flags, FALSE); - g_list_free(users); - g_list_free(flags); - - /* Set topic */ - if (channel->topic) - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, channel->topic); - - /* Set nick */ - purple_conv_chat_set_nick(PURPLE_CONV_CHAT(convo), conn->local_entry->nickname); -} - -char *silcpurple_get_chat_name(GHashTable *data) -{ - return g_strdup(g_hash_table_lookup(data, "channel")); -} - -void silcpurple_chat_join(PurpleConnection *gc, GHashTable *data) -{ - SilcPurple sg = gc->proto_data; - 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); - 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); - 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(PurpleConnection *gc, int id, const char *msg, - const char *name) -{ - SilcPurple sg = gc->proto_data; - 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 == 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) == 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(PurpleConnection *gc, int id) -{ - SilcPurple sg = gc->proto_data; - 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 == 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_remove(sg->grps, prv); - 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) == 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); - - 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 == id) { - prv = l->data; - silc_client_del_channel_private_key(client, conn, - chu->channel, - prv->key); - serv_got_chat_left(gc, prv->id); - silc_free(prv); - sg->grps = g_list_remove(sg->grps, prv); - if (!sg->grps) - break; - } -} - -int silcpurple_chat_send(PurpleConnection *gc, int id, const char *msg, PurpleMessageFlags msgflags) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcHashTableList htl; - SilcChannelUser chu; - SilcChannelEntry channel = NULL; - SilcChannelPrivateKey key = NULL; - SilcUInt32 flags; - int ret; - char *msg2, *tmp; - gboolean found = FALSE; - gboolean sign = purple_account_get_bool(sg->account, "sign-verify", FALSE); - - 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")); - 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 == 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) == id ) { - found = TRUE; - break; - } - } - silc_hash_table_list_reset(&htl); - if (!found) { - g_free(tmp); - return 0; - } - channel = chu->channel; - } - - /* Send channel message */ - ret = silc_client_send_channel_message(client, conn, channel, key, - flags, (unsigned char *)msg2, - strlen(msg2), TRUE); - if (ret) { - 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(PurpleConnection *gc, int id, const char *topic) -{ - SilcPurple sg = gc->proto_data; - 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 == 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) == 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(PurpleConnection *gc) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - GList *fields = NULL; - PurpleRoomlistField *f; - - if (!conn) - return NULL; - - if (sg->roomlist) - purple_roomlist_unref(sg->roomlist); - - sg->roomlist_cancelled = FALSE; - - sg->roomlist = purple_roomlist_new(purple_connection_get_account(gc)); - f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", "channel", TRUE); - fields = g_list_append(fields, f); - f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_INT, - _("Users"), "users", FALSE); - fields = g_list_append(fields, f); - f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, - _("Topic"), "topic", FALSE); - fields = g_list_append(fields, f); - purple_roomlist_set_fields(sg->roomlist, fields); - - /* Call LIST */ - silc_client_command_call(client, conn, "LIST"); - - purple_roomlist_set_in_progress(sg->roomlist, TRUE); - - return sg->roomlist; -} - -void silcpurple_roomlist_cancel(PurpleRoomlist *list) -{ - PurpleConnection *gc = purple_account_get_connection(list->account); - SilcPurple sg; - - if (!gc) - return; - sg = gc->proto_data; - - purple_roomlist_set_in_progress(list, FALSE); - if (sg->roomlist == list) { - purple_roomlist_unref(sg->roomlist); - sg->roomlist = NULL; - sg->roomlist_cancelled = TRUE; - } -} diff -r 0cc718e10344 -r 4f2d99bcb195 libpurple/protocols/silc10/ft.c --- a/libpurple/protocols/silc10/ft.c Mon Aug 22 06:32:44 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,412 +0,0 @@ -/* - - silcpurple_ft.c - - Author: Pekka Riikonen - - Copyright (C) 2004 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 "silcincludes.h" -#include "silcclient.h" -#include "silcpurple.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. */ - -typedef struct { - SilcPurple sg; - SilcClientEntry client_entry; - SilcUInt32 session_id; - char *hostname; - SilcUInt16 port; - PurpleXfer *xfer; - - SilcClientFileName completion; - void *completion_context; -} *SilcPurpleXfer; - -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) -{ - SilcPurpleXfer xfer = context; - PurpleConnection *gc = xfer->sg->gc; - char tmp[256]; - - if (status == SILC_CLIENT_FILE_MONITOR_CLOSED) { - purple_xfer_unref(xfer->xfer); - silc_free(xfer); - 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); - } else if (error == SILC_CLIENT_FILE_PERMISSION_DENIED) { - purple_notify_error(gc, _("Secure File Transfer"), - _("Error during file transfer"), - _("Permission denied")); - } else if (error == SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED) { - purple_notify_error(gc, _("Secure File Transfer"), - _("Error during file transfer"), - _("Key agreement failed")); - } 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")); - } else { - purple_notify_error(gc, _("Secure File Transfer"), - _("Error during file transfer"), NULL); - } - silc_client_file_close(client, conn, session_id); - purple_xfer_unref(xfer->xfer); - silc_free(xfer); - return; - } - - /* Update file transfer UI */ - if (!offset && filesize) - purple_xfer_set_size(xfer->xfer, filesize); - if (offset && filesize) { - xfer->xfer->bytes_sent = offset; - xfer->xfer->bytes_remaining = filesize - offset; - } - purple_xfer_update_progress(xfer->xfer); - - if (status == SILC_CLIENT_FILE_MONITOR_SEND || - status == SILC_CLIENT_FILE_MONITOR_RECEIVE) { - if (offset == filesize) { - /* Download finished */ - purple_xfer_set_completed(xfer->xfer, TRUE); - silc_client_file_close(client, conn, session_id); - } - } -} - -static void -silcpurple_ftp_cancel(PurpleXfer *x) -{ - SilcPurpleXfer xfer = x->data; - xfer->xfer->status = PURPLE_XFER_STATUS_CANCEL_LOCAL; - purple_xfer_update_progress(xfer->xfer); - silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id); -} - -static void -silcpurple_ftp_ask_name_cancel(PurpleXfer *x) -{ - SilcPurpleXfer xfer = x->data; - - /* Cancel the transmission */ - xfer->completion(NULL, xfer->completion_context); - silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id); -} - -static void -silcpurple_ftp_ask_name_ok(PurpleXfer *x) -{ - SilcPurpleXfer xfer = x->data; - const char *name; - - name = purple_xfer_get_local_filename(x); - g_unlink(name); - xfer->completion(name, xfer->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) -{ - SilcPurpleXfer xfer = context; - - xfer->completion = completion; - xfer->completion_context = completion_context; - - purple_xfer_set_init_fnc(xfer->xfer, silcpurple_ftp_ask_name_ok); - purple_xfer_set_request_denied_fnc(xfer->xfer, silcpurple_ftp_ask_name_cancel); - - /* Request to save the file */ - purple_xfer_set_filename(xfer->xfer, remote_filename); - purple_xfer_request(xfer->xfer); -} - -static void -silcpurple_ftp_request_result(PurpleXfer *x) -{ - SilcPurpleXfer xfer = x->data; - SilcClientFileError status; - PurpleConnection *gc = xfer->sg->gc; - - if (purple_xfer_get_status(x) != PURPLE_XFER_STATUS_ACCEPTED) - return; - - /* Start the file transfer */ - status = silc_client_file_receive(xfer->sg->client, xfer->sg->conn, - silcpurple_ftp_monitor, xfer, - NULL, xfer->session_id, - silcpurple_ftp_ask_name, xfer); - switch (status) { - case SILC_CLIENT_FILE_OK: - return; - break; - - case SILC_CLIENT_FILE_UNKNOWN_SESSION: - purple_notify_error(gc, _("Secure File Transfer"), - _("No file transfer session active"), NULL); - break; - - case SILC_CLIENT_FILE_ALREADY_STARTED: - purple_notify_error(gc, _("Secure File Transfer"), - _("File transfer already started"), NULL); - break; - - case SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED: - purple_notify_error(gc, _("Secure File Transfer"), - _("Could not perform key agreement for file transfer"), - NULL); - break; - - default: - purple_notify_error(gc, _("Secure File Transfer"), - _("Could not start the file transfer"), NULL); - break; - } - - /* Error */ - purple_xfer_unref(xfer->xfer); - g_free(xfer->hostname); - silc_free(xfer); -} - -static void -silcpurple_ftp_request_denied(PurpleXfer *x) -{ - -} - -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 = gc->proto_data; - SilcPurpleXfer xfer; - - xfer = silc_calloc(1, sizeof(*xfer)); - if (!xfer) { - silc_client_file_close(sg->client, sg->conn, session_id); - return; - } - - xfer->sg = sg; - xfer->client_entry = client_entry; - xfer->session_id = session_id; - xfer->hostname = g_strdup(hostname); - xfer->port = port; - xfer->xfer = purple_xfer_new(xfer->sg->account, PURPLE_XFER_RECEIVE, - xfer->client_entry->nickname); - if (!xfer->xfer) { - silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id); - g_free(xfer->hostname); - silc_free(xfer); - return; - } - purple_xfer_set_init_fnc(xfer->xfer, silcpurple_ftp_request_result); - purple_xfer_set_request_denied_fnc(xfer->xfer, silcpurple_ftp_request_denied); - purple_xfer_set_cancel_recv_fnc(xfer->xfer, silcpurple_ftp_cancel); - xfer->xfer->remote_ip = g_strdup(hostname); - xfer->xfer->remote_port = port; - xfer->xfer->data = xfer; - - /* File transfer request */ - purple_xfer_request(xfer->xfer); -} - -static void -silcpurple_ftp_send_cancel(PurpleXfer *x) -{ - SilcPurpleXfer xfer = x->data; - silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id); - purple_xfer_unref(xfer->xfer); - g_free(xfer->hostname); - silc_free(xfer); -} - -static void -silcpurple_ftp_send(PurpleXfer *x) -{ - SilcPurpleXfer xfer = x->data; - const char *name; - char *local_ip = NULL, *remote_ip = NULL; - gboolean local = TRUE; - - name = purple_xfer_get_local_filename(x); - - /* 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(xfer->sg->conn->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(xfer->sg->conn->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(); - - /* Send the file */ - silc_client_file_send(xfer->sg->client, xfer->sg->conn, - silcpurple_ftp_monitor, xfer, - local_ip, 0, !local, xfer->client_entry, - name, &xfer->session_id); - - silc_free(local_ip); - silc_free(remote_ip); -} - -static void -silcpurple_ftp_send_file_resolved(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - 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); - silc_free(context); - return; - } - - silcpurple_ftp_send_file(client->application, (const char *)context, NULL); - silc_free(context); -} - -PurpleXfer *silcpurple_ftp_new_xfer(PurpleConnection *gc, const char *name) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcClientEntry *clients; - SilcUInt32 clients_count; - SilcPurpleXfer xfer; - char *nickname; - - g_return_val_if_fail(name != NULL, NULL); - - if (!silc_parse_userfqdn(name, &nickname, NULL)) - return NULL; - - /* Find client entry */ - clients = silc_client_get_clients_local(client, conn, nickname, name, - &clients_count); - if (!clients) { - silc_client_get_clients(client, conn, nickname, NULL, - silcpurple_ftp_send_file_resolved, - strdup(name)); - silc_free(nickname); - return NULL; - } - - xfer = silc_calloc(1, sizeof(*xfer)); - - g_return_val_if_fail(xfer != NULL, NULL); - - xfer->sg = sg; - xfer->client_entry = clients[0]; - xfer->xfer = purple_xfer_new(xfer->sg->account, PURPLE_XFER_SEND, - xfer->client_entry->nickname); - if (!xfer->xfer) { - silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id); - g_free(xfer->hostname); - silc_free(xfer); - return NULL; - } - purple_xfer_set_init_fnc(xfer->xfer, silcpurple_ftp_send); - purple_xfer_set_request_denied_fnc(xfer->xfer, silcpurple_ftp_request_denied); - purple_xfer_set_cancel_send_fnc(xfer->xfer, silcpurple_ftp_send_cancel); - xfer->xfer->data = xfer; - - silc_free(clients); - silc_free(nickname); - - return xfer->xfer; -} - -void silcpurple_ftp_send_file(PurpleConnection *gc, const char *name, const char *file) -{ - PurpleXfer *xfer = silcpurple_ftp_new_xfer(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); -} diff -r 0cc718e10344 -r 4f2d99bcb195 libpurple/protocols/silc10/ops.c --- a/libpurple/protocols/silc10/ops.c Mon Aug 22 06:32:44 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2063 +0,0 @@ -/* - - silcpurple_ops.c - - Author: Pekka Riikonen - - Copyright (C) 2004 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 "silcincludes.h" -#include "silcclient.h" -#include "silcpurple.h" -#include "imgstore.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); - -/* 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. */ - -static void -silc_say(SilcClient client, SilcClientConnection conn, - SilcClientMessageType type, char *msg, ...) -{ - /* Nothing */ -} - -#ifdef HAVE_SILCMIME_H -/* Processes incoming MIME message. Can be private message or channel - message. */ - -static void -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 = gc->proto_data; - const char *type; - const unsigned char *data; - SilcUInt32 data_len; - PurpleMessageFlags cflags = 0; - PurpleConversation *convo = NULL; - - if (!mime) - return; - - /* 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; - - /* Process the complete message */ - silcpurple_mime_message(client, conn, sender, channel, - payload, key, flags, mime, FALSE); - return; - } - - /* Check for multipart message */ - if (silc_mime_is_multipart(mime)) { - SilcMime p; - const char *mtype; - SilcDList parts = silc_mime_get_multiparts(mime, &mtype); - - /* Only "mixed" type supported */ - if (strcmp(mtype, "mixed")) - goto out; - - silc_dlist_start(parts); - while ((p = silc_dlist_get(parts)) != SILC_LIST_END) { - /* Recursively process parts */ - silcpurple_mime_message(client, conn, sender, channel, - payload, key, flags, p, TRUE); - } - 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); - goto out; - } - - /* Image */ - if (strstr(type, "image/png") || - strstr(type, "image/jpeg") || - strstr(type, "image/gif") || - strstr(type, "image/tiff")) { - char tmp[32]; - int imgid; - - /* Get channel convo (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; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - prv->channel, sg->account); - break; - } - } - if (channel && !convo) - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (channel && !convo) - goto out; - - imgid = purple_imgstore_add_with_id(g_memdup(data, data_len), data_len, ""); - if (imgid) { - cflags |= PURPLE_MESSAGE_IMAGES | PURPLE_MESSAGE_RECV; - g_snprintf(tmp, sizeof(tmp), "", imgid); - - if (channel) - serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), - sender->nickname ? - sender->nickname : - "", cflags, - tmp, time(NULL)); - else - serv_got_im(gc, sender->nickname ? - sender->nickname : "", - tmp, cflags, time(NULL)); - - purple_imgstore_unref_by_id(imgid); - cflags = 0; - } - 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); - goto out; - } - - out: - if (!recursive) - silc_mime_free(mime); -} -#endif /* HAVE_SILCMIME_H */ - -/* 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 = gc->proto_data; - PurpleConversation *convo = NULL; - char *msg, *tmp; - - if (!message) - return; - - if (key) { - GList *l; - SilcPurplePrvgrp prv; - - for (l = sg->grps; l; l = l->next) - if (((SilcPurplePrvgrp)l->data)->key == key) { - prv = l->data; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - prv->channel, sg->account); - break; - } - } - if (!convo) - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - 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 */ -#ifdef HAVE_SILCMIME_H - SilcMime mime; - mime = silc_mime_decode(message, message_len); - silcpurple_mime_message(client, conn, sender, channel, payload, - key, flags, mime, FALSE); -#else - char type[128], enc[128]; - unsigned char *data; - SilcUInt32 data_len; - - memset(type, 0, sizeof(type)); - memset(enc, 0, sizeof(enc)); - - if (!silc_mime_parse(message, message_len, NULL, 0, - type, sizeof(type) - 1, enc, sizeof(enc) - 1, &data, - &data_len)) - return; - - if (!strcmp(type, "application/x-wb") && - !strcmp(enc, "binary") && - !purple_account_get_bool(sg->account, "block-wb", FALSE)) - silcpurple_wb_receive_ch(client, conn, sender, channel, - payload, flags, data, data_len); -#endif - 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 */ - serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), - sender->nickname ? - sender->nickname : "", 0, - tmp, time(NULL)); - g_free(tmp); - g_free(msg); - return; - } - - if (flags & SILC_MESSAGE_FLAG_NOTICE) { - msg = g_strdup_printf("(notice) %s %s", - sender->nickname ? - sender->nickname : "", - (const char *)message); - if (!msg) - return; - - /* Send to Purple */ - purple_conversation_write(convo, NULL, (const char *)msg, - PURPLE_MESSAGE_SYSTEM, time(NULL)); - g_free(msg); - return; - } - - if (flags & SILC_MESSAGE_FLAG_UTF8) { - tmp = g_markup_escape_text((const char *)message, -1); - /* Send to Purple */ - serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), - sender->nickname ? - sender->nickname : "", 0, - tmp, time(NULL)); - 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 = gc->proto_data; - PurpleConversation *convo = NULL; - char *msg, *tmp; - - if (!message) - return; - - if (sender->nickname) - /* XXX - Should this be PURPLE_CONV_TYPE_IM? */ - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, - sender->nickname, sg->account); - - if (flags & SILC_MESSAGE_FLAG_SIGNED && - purple_account_get_bool(sg->account, "sign-verify", FALSE)) { - /* XXX */ - } - - if (flags & SILC_MESSAGE_FLAG_DATA) { -#ifdef HAVE_SILCMIME_H - /* Process MIME message */ - SilcMime mime; - mime = silc_mime_decode(message, message_len); - silcpurple_mime_message(client, conn, sender, NULL, payload, - NULL, flags, mime, FALSE); -#else - char type[128], enc[128]; - unsigned char *data; - SilcUInt32 data_len; - - memset(type, 0, sizeof(type)); - memset(enc, 0, sizeof(enc)); - - if (!silc_mime_parse(message, message_len, NULL, 0, - type, sizeof(type) - 1, enc, sizeof(enc) - 1, &data, - &data_len)) - return; - - if (!strcmp(type, "application/x-wb") && - !strcmp(enc, "binary") && - !purple_account_get_bool(sg->account, "block-wb", FALSE)) - silcpurple_wb_receive(client, conn, sender, payload, - flags, data, data_len); -#endif - return; - } - - if (flags & SILC_MESSAGE_FLAG_ACTION && convo) { - msg = g_strdup_printf("/me %s", - (const char *)message); - if (!msg) - return; - - tmp = g_markup_escape_text(msg, -1); - /* Send to Purple */ - serv_got_im(gc, sender->nickname ? - 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) %s %s", - sender->nickname ? - sender->nickname : "", - (const char *)message); - if (!msg) - return; - - /* Send to Purple */ - purple_conversation_write(convo, NULL, (const char *)msg, - PURPLE_MESSAGE_SYSTEM, time(NULL)); - g_free(msg); - return; - } - - if (flags & SILC_MESSAGE_FLAG_UTF8) { - tmp = g_markup_escape_text((const char *)message, -1); - /* Send to Purple */ - serv_got_im(gc, sender->nickname ? - sender->nickname : "", - tmp, 0, time(NULL)); - 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; - SilcPurple sg = gc->proto_data; - PurpleConversation *convo; - 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; - int i; - - va_start(va, type); - memset(buf, 0, sizeof(buf)); - - switch (type) { - - case SILC_NOTIFY_TYPE_NONE: - break; - - case SILC_NOTIFY_TYPE_INVITE: - { - GHashTable *components; - 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, strdup("channel"), strdup(name)); - 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; - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - break; - - /* Join user to channel */ - g_snprintf(buf, sizeof(buf), "%s@%s", - client_entry->username, client_entry->hostname); - purple_conv_chat_add_user(PURPLE_CONV_CHAT(convo), - g_strdup(client_entry->nickname), buf, PURPLE_CBFLAGS_NONE, TRUE); - - break; - - case SILC_NOTIFY_TYPE_LEAVE: - client_entry = va_arg(va, SilcClientEntry); - channel = va_arg(va, SilcChannelEntry); - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - break; - - /* Remove user from channel */ - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), - client_entry->nickname, NULL); - - break; - - case SILC_NOTIFY_TYPE_SIGNOFF: - client_entry = va_arg(va, SilcClientEntry); - tmp = va_arg(va, char *); - - if (!client_entry->nickname) - break; - - /* Remove from all channels */ - silc_hash_table_list(client_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - chu->channel->channel_name, sg->account); - if (!convo) - continue; - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), - 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); - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - 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 %s to: %s"), - client_entry->nickname, channel->channel_name, tmp2); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname, - buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), - 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 %s to: %s"), - server_entry->server_name, channel->channel_name, tmp2); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), server_entry->server_name, - buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), - 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 %s to: %s"), - channel->channel_name, channel->channel_name, tmp2); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name, - buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), - channel->channel_name, tmp); - } else { - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, tmp); - } - - g_free(tmp2); - - break; - - } - case SILC_NOTIFY_TYPE_NICK_CHANGE: - client_entry = va_arg(va, SilcClientEntry); - client_entry2 = va_arg(va, SilcClientEntry); - - if (!strcmp(client_entry->nickname, client_entry2->nickname)) - break; - - /* Change nick on all channels */ - silc_hash_table_list(client_entry2->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - chu->channel->channel_name, sg->account); - if (!convo) - continue; - if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(convo), client_entry->nickname)) - purple_conv_chat_rename_user(PURPLE_CONV_CHAT(convo), - client_entry->nickname, - client_entry2->nickname); - } - 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, SilcBuffer); - channel = va_arg(va, SilcChannelEntry); - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - 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), - _("%s set channel %s modes to: %s"), name, - channel->channel_name, buf2); - } else { - g_snprintf(buf, sizeof(buf), - _("%s removed all channel %s modes"), name, - channel->channel_name); - } - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name, - buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - break; - - case SILC_NOTIFY_TYPE_CUMODE_CHANGE: - { - PurpleConvChatBuddyFlags flags = PURPLE_CBFLAGS_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); - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - 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), - _("%s set %s's modes to: %s"), name, - client_entry2->nickname, buf2); - if (mode & SILC_CHANNEL_UMODE_CHANFO) - flags |= PURPLE_CBFLAGS_FOUNDER; - if (mode & SILC_CHANNEL_UMODE_CHANOP) - flags |= PURPLE_CBFLAGS_OP; - } else { - g_snprintf(buf, sizeof(buf), - _("%s removed all %s's modes"), name, - client_entry2->nickname); - } - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name, - buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(convo), 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); - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - break; - - if (client_entry == conn->local_entry) { - /* Remove us from channel */ - g_snprintf(buf, sizeof(buf), - _("You have been kicked off %s by %s (%s)"), - channel->channel_name, client_entry2->nickname, - tmp ? tmp : ""); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname, - buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo))); - } else { - /* Remove user from channel */ - g_snprintf(buf, sizeof(buf), _("Kicked by %s (%s)"), - client_entry2->nickname, tmp ? tmp : ""); - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), - 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->nickname) - break; - - 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)) { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - chu->channel->channel_name, sg->account); - if (!convo) - continue; - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname, - buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo))); - } - 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)) { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - chu->channel->channel_name, sg->account); - if (!convo) - continue; - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), - client_entry->nickname, tmp); - } - silc_hash_table_list_reset(&htl); - } - - break; - - case SILC_NOTIFY_TYPE_CHANNEL_CHANGE: - break; - - case SILC_NOTIFY_TYPE_SERVER_SIGNOFF: - { - int i; - SilcClientEntry *clients; - SilcUInt32 clients_count; - - (void)va_arg(va, void *); - clients = va_arg(va, SilcClientEntry *); - clients_count = va_arg(va, SilcUInt32); - - for (i = 0; i < clients_count; i++) { - if (!clients[i]->nickname) - break; - - /* Remove from all channels */ - silc_hash_table_list(clients[i]->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - convo = - purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - chu->channel->channel_name, sg->account); - if (!convo) - continue; - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), - clients[i]->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); - } - 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) { - PurpleBlistNode *gnode, *cnode, *bnode; - const char *f; - - 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 (gnode = purple_get_blist()->root; gnode; - gnode = gnode->next) { - if (!PURPLE_BLIST_NODE_IS_GROUP(gnode)) - continue; - for (cnode = gnode->child; cnode; cnode = cnode->next) { - if( !PURPLE_BLIST_NODE_IS_CONTACT(cnode)) - continue; - for (bnode = cnode->child; bnode; - bnode = bnode->next) { - if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) - continue; - b = (PurpleBuddy *)bnode; - if (b->account != gc->account) - continue; - f = purple_blist_node_get_string(bnode, "public-key"); - if (f && !strcmp(f, buf)) - goto cont; - b = NULL; - } - } - } - } - cont: - if (!b) { - /* Find buddy by nickname */ - b = purple_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(b->proto_data); - b->proto_data = 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_prpl_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_prpl_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_prpl_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_prpl_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 in the command function. - If error occurs it will be called as well. `conn' is the associated - client connection. `cmd_context' is the command context that was - originally sent to the command. `success' is FALSE if error occurred - during command. `command' is the command being processed. It must be - noted that this is not reply from server. This is merely called just - after application has called the command. Just to tell application - that the command really was processed. */ - -static void -silc_command(SilcClient client, SilcClientConnection conn, - SilcClientCommandContext cmd_context, bool success, - SilcCommand command, SilcStatus status) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - - switch (command) { - - case SILC_COMMAND_CMODE: - if (cmd_context->argc == 3 && - !strcmp((char *)cmd_context->argv[2], "+C")) - sg->chpk = TRUE; - else - sg->chpk = FALSE; - break; - - default: - break; - } -} - -#if 0 -static void -silcpurple_whois_more(SilcClientEntry client_entry, gint id) -{ - SilcAttributePayload attr; - SilcAttribute attribute; - char *buf; - GString *s; - SilcVCardStruct vcard; - int i; - - if (id != 0) - return; - - memset(&vcard, 0, sizeof(vcard)); - - s = g_string_new(""); - - 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; - g_string_append_printf(s, "%s:\n\n", _("Personal Information")); - if (vcard.full_name) - g_string_append_printf(s, "%s:\t\t%s\n", - _("Full Name"), - vcard.full_name); - if (vcard.first_name) - g_string_append_printf(s, "%s:\t%s\n", - _("First Name"), - vcard.first_name); - if (vcard.middle_names) - g_string_append_printf(s, "%s:\t%s\n", - _("Middle Name"), - vcard.middle_names); - if (vcard.family_name) - g_string_append_printf(s, "%s:\t%s\n", - _("Family Name"), - vcard.family_name); - if (vcard.nickname) - g_string_append_printf(s, "%s:\t\t%s\n", - _("Nickname"), - vcard.nickname); - if (vcard.bday) - g_string_append_printf(s, "%s:\t\t%s\n", - _("Birth Day"), - vcard.bday); - if (vcard.title) - g_string_append_printf(s, "%s:\t\t%s\n", - _("Job Title"), - vcard.title); - if (vcard.role) - g_string_append_printf(s, "%s:\t\t%s\n", - _("Job Role"), - vcard.role); - if (vcard.org_name) - g_string_append_printf(s, "%s:\t%s\n", - _("Organization"), - vcard.org_name); - if (vcard.org_unit) - g_string_append_printf(s, "%s:\t\t%s\n", - _("Unit"), - vcard.org_unit); - if (vcard.url) - g_string_append_printf(s, "%s:\t%s\n", - _("Homepage"), - vcard.url); - if (vcard.label) - g_string_append_printf(s, "%s:\t%s\n", - _("Address"), - vcard.label); - for (i = 0; i < vcard.num_tels; i++) { - if (vcard.tels[i].telnum) - g_string_append_printf(s, "%s:\t\t\t%s\n", - _("Phone"), - vcard.tels[i].telnum); - } - for (i = 0; i < vcard.num_emails; i++) { - if (vcard.emails[i].address) - g_string_append_printf(s, "%s:\t\t%s\n", - _("Email"), - vcard.emails[i].address); - } - if (vcard.note) - g_string_append_printf(s, "\n%s:\t\t%s\n", - _("Note"), - vcard.note); - break; - } - } - - buf = g_string_free(s, FALSE); - purple_notify_info(NULL, _("User Information"), _("User Information"), - buf); - g_free(buf); -} -#endif - -/* Command reply handler. This function is called always in the command reply - function. If error occurs it will be called as well. Normal scenario - is that it will be called after the received command data has been parsed - and processed. The function is used to pass the received command data to - the application. - - `conn' is the associated client connection. `cmd_payload' is the command - payload data received from server and it can be ignored. It is provided - if the application would like to re-parse the received command data, - however, it must be noted that the data is parsed already by the library - thus the payload can be ignored. `success' is FALSE if error occurred. - In this case arguments are not sent to the application. The `status' is - the command reply status server returned. The `command' is the command - reply being processed. The function has variable argument list and each - command defines the number and type of arguments it passes to the - application (on error they are not sent). */ - -static void -silc_command_reply(SilcClient client, SilcClientConnection conn, - SilcCommandPayload cmd_payload, bool success, - SilcCommand command, SilcStatus status, ...) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - PurpleConversation *convo; - va_list vp; - - va_start(vp, status); - - switch (command) { - case SILC_COMMAND_JOIN: - { - SilcChannelEntry channel_entry; - - if (!success) { - purple_notify_error(gc, _("Join Chat"), _("Cannot join channel"), - silc_get_status_message(status)); - return; - } - - (void)va_arg(vp, char *); - channel_entry = va_arg(vp, SilcChannelEntry); - - /* Resolve users on channel */ - silc_client_get_clients_by_channel(client, conn, channel_entry, - silcpurple_chat_join_done, - channel_entry); - } - break; - - case SILC_COMMAND_LEAVE: - break; - - case SILC_COMMAND_USERS: - break; - - case SILC_COMMAND_WHOIS: - { - SilcUInt32 idle, mode; - SilcBuffer channels, user_modes; - SilcClientEntry client_entry; - char tmp[1024], *tmp2; - char *moodstr, *statusstr, *contactstr, *langstr, *devicestr, *tzstr, *geostr; - PurpleNotifyUserInfo *user_info; - - if (!success) { - purple_notify_error(gc, _("User Information"), - _("Cannot get user information"), - silc_get_status_message(status)); - break; - } - - client_entry = va_arg(vp, SilcClientEntry); - if (!client_entry->nickname) - break; - (void)va_arg(vp, char *); - (void)va_arg(vp, char *); - (void)va_arg(vp, char *); - channels = va_arg(vp, SilcBuffer); - mode = va_arg(vp, SilcUInt32); - idle = va_arg(vp, SilcUInt32); - (void)va_arg(vp, unsigned char *); - user_modes = va_arg(vp, SilcBuffer); - - user_info = purple_notify_user_info_new(); - tmp2 = g_markup_escape_text(client_entry->nickname, -1); - purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp2); - g_free(tmp2); - if (client_entry->realname) { - tmp2 = g_markup_escape_text(client_entry->realname, -1); - purple_notify_user_info_add_pair(user_info, _("Real Name"), tmp2); - g_free(tmp2); - } - if (client_entry->username) { - tmp2 = g_markup_escape_text(client_entry->username, -1); - if (client_entry->hostname) { - gchar *tmp3; - tmp3 = g_strdup_printf("%s@%s", tmp2, client_entry->hostname); - purple_notify_user_info_add_pair(user_info, _("Username"), tmp3); - g_free(tmp3); - } else - purple_notify_user_info_add_pair(user_info, _("Username"), tmp2); - g_free(tmp2); - } - - 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(user_info, _("User Modes"), tmp); - } - - silcpurple_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr); - if (moodstr) { - purple_notify_user_info_add_pair(user_info, _("Mood"), moodstr); - g_free(moodstr); - } - - if (statusstr) { - tmp2 = g_markup_escape_text(statusstr, -1); - purple_notify_user_info_add_pair(user_info, _("Status Text"), tmp2); - g_free(statusstr); - g_free(tmp2); - } - - if (contactstr) { - purple_notify_user_info_add_pair(user_info, _("Preferred Contact"), contactstr); - g_free(contactstr); - } - - if (langstr) { - purple_notify_user_info_add_pair(user_info, _("Preferred Language"), langstr); - g_free(langstr); - } - - if (devicestr) { - purple_notify_user_info_add_pair(user_info, _("Device"), devicestr); - g_free(devicestr); - } - - if (tzstr) { - purple_notify_user_info_add_pair(user_info, _("Timezone"), tzstr); - g_free(tzstr); - } - - if (geostr) { - purple_notify_user_info_add_pair(user_info, _("Geolocation"), geostr); - g_free(geostr); - } - - if (client_entry->server) - purple_notify_user_info_add_pair(user_info, _("Server"), client_entry->server); - - if (channels && user_modes) { - SilcUInt32 *umodes; - SilcDList list = - silc_channel_payload_parse_list(channels->data, - channels->len); - if (list && silc_get_mode_list(user_modes, - silc_dlist_count(list), - &umodes)) { - SilcChannelPayload entry; - int i = 0; - - memset(tmp, 0, sizeof(tmp)); - silc_dlist_start(list); - while ((entry = silc_dlist_get(list)) - != SILC_LIST_END) { - SilcUInt32 name_len; - char *m = silc_client_chumode_char(umodes[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); - - } - tmp2 = g_markup_escape_text(tmp, -1); - purple_notify_user_info_add_pair(user_info, _("Currently on"), tmp2); - g_free(tmp2); - silc_free(umodes); - } - } - - 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); - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint); - purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint); - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); - } - -#if 0 /* XXX for now, let's not show attrs here */ - if (client_entry->attrs) - purple_request_action(gc, _("User Information"), - _("User Information"), - buf, 1, client_entry, 2, - _("OK"), G_CALLBACK(silcpurple_whois_more), - _("_More..."), G_CALLBACK(silcpurple_whois_more), gc->account, NULL, NULL); - else -#endif - 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, *tmp; - PurpleNotifyUserInfo *user_info; - - if (!success) { - purple_notify_error(gc, _("User Information"), - _("Cannot get user information"), - silc_get_status_message(status)); - break; - } - - client_entry = va_arg(vp, SilcClientEntry); - nickname = va_arg(vp, char *); - username = va_arg(vp, char *); - realname = va_arg(vp, char *); - if (!nickname) - break; - - user_info = purple_notify_user_info_new(); - tmp = g_markup_escape_text(nickname, -1); - purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp); - g_free(tmp); - if (realname) { - tmp = g_markup_escape_text(realname, -1); - purple_notify_user_info_add_pair(user_info, _("Real Name"), tmp); - g_free(tmp); - } - if (username) { - tmp = g_markup_escape_text(username, -1); - if (client_entry && client_entry->hostname) { - gchar *tmp3; - tmp3 = g_strdup_printf("%s@%s", tmp, client_entry->hostname); - purple_notify_user_info_add_pair(user_info, _("Username"), tmp3); - g_free(tmp3); - } else - purple_notify_user_info_add_pair(user_info, _("Username"), tmp); - g_free(tmp); - } - if (client_entry && client_entry->server) - purple_notify_user_info_add_pair(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); - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint); - purple_notify_user_info_add_pair(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: - if (!success) { - purple_notify_error(gc, _("Detach From Server"), _("Cannot detach"), - silc_get_status_message(status)); - return; - } - break; - - case SILC_COMMAND_TOPIC: - { - SilcChannelEntry channel; - - if (!success) { - purple_notify_error(gc, _("Topic"), _("Cannot set topic"), - silc_get_status_message(status)); - return; - } - - channel = va_arg(vp, SilcChannelEntry); - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) { - purple_debug_error("silc", "Got a topic for %s, which doesn't exist\n", - channel->channel_name); - break; - } - - /* Set topic */ - if (channel->topic) - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, channel->topic); - } - break; - - case SILC_COMMAND_NICK: - { - /* I don't think we should need to do this because the server should - * be sending a SILC_NOTIFY_TYPE_NICK_CHANGE when we change our own - * nick, but it isn't, so we deal with it here instead. Stu. */ - SilcClientEntry local_entry; - SilcHashTableList htl; - SilcChannelUser chu; - const char *oldnick; - - if (!success) { - purple_notify_error(gc, _("Nick"), _("Failed to change nickname"), - silc_get_status_message(status)); - return; - } - - local_entry = va_arg(vp, SilcClientEntry); - - /* Change nick on all channels */ - silc_hash_table_list(local_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - chu->channel->channel_name, sg->account); - if (!convo) - continue; - oldnick = purple_conv_chat_get_nick(PURPLE_CONV_CHAT(convo)); - if (strcmp(oldnick, purple_normalize(purple_conversation_get_account(convo), local_entry->nickname))) { - purple_conv_chat_rename_user(PURPLE_CONV_CHAT(convo), - oldnick, local_entry->nickname); - purple_conv_chat_set_nick(PURPLE_CONV_CHAT(convo), local_entry->nickname); - } - } - silc_hash_table_list_reset(&htl); - - purple_connection_set_display_name(gc, local_entry->nickname); - } - break; - - case SILC_COMMAND_LIST: - { - char *topic, *name; - int usercount; - PurpleRoomlistRoom *room; - - if (sg->roomlist_cancelled) - break; - - if (!success) { - purple_notify_error(gc, _("Error"), _("Error retrieving room list"), - silc_get_status_message(status)); - purple_roomlist_set_in_progress(sg->roomlist, FALSE); - purple_roomlist_unref(sg->roomlist); - sg->roomlist = NULL; - return; - } - - (void)va_arg(vp, SilcChannelEntry); - name = va_arg(vp, char *); - if (!name) { - purple_notify_error(gc, _("Roomlist"), _("Cannot get room list"), - silc_get_status_message(status)); - purple_roomlist_set_in_progress(sg->roomlist, FALSE); - purple_roomlist_unref(sg->roomlist); - sg->roomlist = NULL; - return; - } - topic = va_arg(vp, char *); - usercount = va_arg(vp, int); - - room = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM, name, NULL); - purple_roomlist_room_add_field(sg->roomlist, room, name); - purple_roomlist_room_add_field(sg->roomlist, room, - SILC_32_TO_PTR(usercount)); - purple_roomlist_room_add_field(sg->roomlist, room, - topic ? topic : ""); - purple_roomlist_room_add(sg->roomlist, room); - - if (status == SILC_STATUS_LIST_END || - status == SILC_STATUS_OK) { - purple_roomlist_set_in_progress(sg->roomlist, FALSE); - purple_roomlist_unref(sg->roomlist); - sg->roomlist = NULL; - } - } - break; - - case SILC_COMMAND_GETKEY: - { - SilcPublicKey public_key; - - if (!success) { - purple_notify_error(gc, _("Get Public Key"), - _("Cannot fetch the public key"), - silc_get_status_message(status)); - return; - } - - (void)va_arg(vp, SilcUInt32); - (void)va_arg(vp, void *); - public_key = va_arg(vp, SilcPublicKey); - - if (!public_key) - purple_notify_error(gc, _("Get Public Key"), - _("Cannot fetch the public key"), - _("No public key was received")); - } - break; - - case SILC_COMMAND_INFO: - { - - char *server_name; - char *server_info; - char tmp[256]; - - if (!success) { - purple_notify_error(gc, _("Server Information"), - _("Cannot get server information"), - silc_get_status_message(status)); - return; - } - - (void)va_arg(vp, SilcServerEntry); - server_name = va_arg(vp, char *); - server_info = va_arg(vp, 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); - } - } - break; - - case SILC_COMMAND_STATS: - { - SilcUInt32 starttime, uptime, my_clients, my_channels, my_server_ops, - my_router_ops, cell_clients, cell_channels, cell_servers, - clients, channels, servers, routers, server_ops, router_ops; - SilcUInt32 buffer_length; - SilcBufferStruct buf; - - unsigned char *server_stats; - char *msg; - - if (!success) { - purple_notify_error(gc, _("Server Statistics"), - _("Cannot get server statistics"), - silc_get_status_message(status)); - return; - } - - server_stats = va_arg(vp, unsigned char *); - buffer_length = va_arg(vp, SilcUInt32); - if (!server_stats || !buffer_length) { - purple_notify_error(gc, _("Server Statistics"), - _("No server statistics available"), NULL); - break; - } - silc_buffer_set(&buf, server_stats, buffer_length); - silc_buffer_unformat(&buf, - SILC_STR_UI_INT(&starttime), - SILC_STR_UI_INT(&uptime), - SILC_STR_UI_INT(&my_clients), - SILC_STR_UI_INT(&my_channels), - SILC_STR_UI_INT(&my_server_ops), - SILC_STR_UI_INT(&my_router_ops), - SILC_STR_UI_INT(&cell_clients), - SILC_STR_UI_INT(&cell_channels), - SILC_STR_UI_INT(&cell_servers), - SILC_STR_UI_INT(&clients), - SILC_STR_UI_INT(&channels), - SILC_STR_UI_INT(&servers), - SILC_STR_UI_INT(&routers), - SILC_STR_UI_INT(&server_ops), - SILC_STR_UI_INT(&router_ops), - SILC_STR_END); - - 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_get_time(starttime), - purple_str_seconds_to_string((int)uptime), - (int)my_clients, (int)my_channels, (int)my_server_ops, (int)my_router_ops, - (int)cell_clients, (int)cell_channels, (int)cell_servers, - (int)clients, (int)channels, (int)servers, (int)routers, - (int)server_ops, (int)router_ops); - - purple_notify_info(gc, NULL, - _("Network Statistics"), msg); - g_free(msg); - } - break; - - case SILC_COMMAND_PING: - { - if (!success) { - purple_notify_error(gc, _("Ping"), _("Ping failed"), - silc_get_status_message(status)); - return; - } - - purple_notify_info(gc, _("Ping"), _("Ping reply received from server"), - NULL); - } - break; - - case SILC_COMMAND_KILL: - if (!success) { - purple_notify_error(gc, _("Kill User"), - _("Could not kill user"), - silc_get_status_message(status)); - return; - } - break; - - case SILC_COMMAND_CMODE: - { - SilcChannelEntry channel_entry; - SilcBuffer channel_pubkeys; - - if (!success) - return; - - channel_entry = va_arg(vp, SilcChannelEntry); - (void)va_arg(vp, SilcUInt32); - (void)va_arg(vp, SilcPublicKey); - channel_pubkeys = va_arg(vp, SilcBuffer); - - if (sg->chpk) - silcpurple_chat_chauth_show(sg, channel_entry, channel_pubkeys); - } - break; - - default: - if (success) - 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(status)); - break; - } - - va_end(vp); -} - - -/* Called to indicate that connection was either successfully established - or connecting failed. This is also the first time application receives - the SilcClientConnection object which it should save somewhere. - If the `success' is FALSE the application must always call the function - silc_client_close_connection. */ - -static void -silc_connected(SilcClient client, SilcClientConnection conn, - SilcClientConnectionStatus status) -{ - PurpleConnection *gc = client->application; - SilcPurple sg; - - if (gc == NULL) { - silc_client_close_connection(client, conn); - return; - } - sg = gc->proto_data; - - switch (status) { - case SILC_CLIENT_CONN_SUCCESS: - case SILC_CLIENT_CONN_SUCCESS_RESUME: - purple_connection_set_state(gc, PURPLE_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); - } - - return; - break; - case SILC_CLIENT_CONN_ERROR: - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Error during 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; - silc_client_close_connection(client, conn); -} - - -/* Called to indicate that connection was disconnected to the server. - The `status' may tell the reason of the disconnection, and if the - `message' is non-NULL it may include the disconnection message - received from server. */ - -static void -silc_disconnected(SilcClient client, SilcClientConnection conn, - SilcStatus status, const char *message) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - - if (sg->resuming && !sg->detaching) - g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); - - sg->conn = NULL; - - /* 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)); -} - - -typedef struct { - SilcGetAuthMeth completion; - void *context; -} *SilcPurpleGetAuthMethod; - -/* Callback called when we've received the authentication method information - from the server after we've requested it. */ - -static void silc_get_auth_method_callback(SilcClient client, - SilcClientConnection conn, - SilcAuthMethod auth_meth, - void *context) -{ - SilcPurpleGetAuthMethod internal = context; - - switch (auth_meth) { - case SILC_AUTH_NONE: - /* No authentication required. */ - (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context); - break; - - case SILC_AUTH_PASSWORD: - /* By returning NULL here the library will ask the passphrase from us - by calling the silc_ask_passphrase. */ - (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context); - break; - - case SILC_AUTH_PUBLIC_KEY: - /* Do not get the authentication data now, the library will generate - it using our default key, if we do not provide it here. */ - (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context); - break; - } - - silc_free(internal); -} - -/* Find authentication method and authentication data by hostname and - port. The hostname may be IP address as well. When the authentication - method has been resolved the `completion' callback with the found - authentication method and authentication data is called. The `conn' - may be NULL. */ - -static void -silc_get_auth_method(SilcClient client, SilcClientConnection conn, - char *hostname, SilcUInt16 port, - SilcGetAuthMeth completion, void *context) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - SilcPurpleGetAuthMethod internal; - const char *password; - - /* Progress */ - if (sg->resuming) - purple_connection_update_progress(gc, _("Resuming session"), 4, 5); - else - purple_connection_update_progress(gc, _("Authenticating connection"), 4, 5); - - /* Check configuration if we have this connection configured. If we - have then return that data immediately, as it's faster way. */ - if (purple_account_get_bool(sg->account, "pubkey-auth", FALSE)) { - completion(TRUE, SILC_AUTH_PUBLIC_KEY, NULL, 0, context); - return; - } - password = purple_connection_get_password(gc); - if (password && *password) { - completion(TRUE, SILC_AUTH_PASSWORD, (unsigned char *)password, strlen(password), context); - return; - } - - /* Resolve the authentication method from server, as we may not know it. */ - internal = silc_calloc(1, sizeof(*internal)); - if (!internal) - return; - internal->completion = completion; - internal->context = context; - silc_client_request_authentication_method(client, conn, - silc_get_auth_method_callback, - internal); -} - - -/* Verifies received public key. The `conn_type' indicates which entity - (server, client etc.) has sent the public key. If user decides to trust - 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, - SilcSocketType conn_type, unsigned char *pk, - SilcUInt32 pk_len, SilcSKEPKType pk_type, - SilcVerifyPublicKey completion, void *context) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - - if (!sg->conn && (conn_type == SILC_SOCKET_TYPE_SERVER || - conn_type == SILC_SOCKET_TYPE_ROUTER)) { - /* Progress */ - if (sg->resuming) - purple_connection_update_progress(gc, _("Resuming session"), 3, 5); - else - purple_connection_update_progress(gc, _("Verifying server public key"), - 3, 5); - } - - /* Verify public key */ - silcpurple_verify_public_key(client, conn, NULL, conn_type, pk, - pk_len, pk_type, completion, context); -} - -typedef struct { - SilcAskPassphrase completion; - void *context; -} *SilcPurpleAskPassphrase; - -static void -silc_ask_passphrase_cb(SilcPurpleAskPassphrase internal, const char *passphrase) -{ - if (!passphrase || !(*passphrase)) - internal->completion(NULL, 0, internal->context); - else - internal->completion((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->completion = 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_connection_get_account(gc), NULL, NULL, internal); -} - - -/* Notifies application that failure packet was received. This is called - if there is some protocol active in the client. The `protocol' is the - protocol context. The `failure' is opaque pointer to the failure - indication. Note, that the `failure' is protocol dependant and - application must explicitly cast it to correct type. Usually `failure' - is 32 bit failure type (see protocol specs for all protocol failure - types). */ - -static void -silc_failure(SilcClient client, SilcClientConnection conn, - SilcProtocol protocol, void *failure) -{ - PurpleConnection *gc = client->application; - char buf[128]; - - memset(buf, 0, sizeof(buf)); - - if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) { - SilcSKEStatus status = (SilcSKEStatus)SILC_PTR_TO_32(failure); - - if (status == SILC_SKE_STATUS_BAD_VERSION) - g_snprintf(buf, sizeof(buf), - _("Failure: Version mismatch, upgrade your client")); - if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) - g_snprintf(buf, sizeof(buf), - _("Failure: Remote does not trust/support your public key")); - if (status == SILC_SKE_STATUS_UNKNOWN_GROUP) - g_snprintf(buf, sizeof(buf), - _("Failure: Remote does not support proposed KE group")); - if (status == SILC_SKE_STATUS_UNKNOWN_CIPHER) - g_snprintf(buf, sizeof(buf), - _("Failure: Remote does not support proposed cipher")); - if (status == SILC_SKE_STATUS_UNKNOWN_PKCS) - g_snprintf(buf, sizeof(buf), - _("Failure: Remote does not support proposed PKCS")); - if (status == SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION) - g_snprintf(buf, sizeof(buf), - _("Failure: Remote does not support proposed hash function")); - if (status == SILC_SKE_STATUS_UNKNOWN_HMAC) - g_snprintf(buf, sizeof(buf), - _("Failure: Remote does not support proposed HMAC")); - if (status == SILC_SKE_STATUS_INCORRECT_SIGNATURE) - g_snprintf(buf, sizeof(buf), _("Failure: Incorrect signature")); - if (status == SILC_SKE_STATUS_INVALID_COOKIE) - g_snprintf(buf, sizeof(buf), _("Failure: Invalid cookie")); - - /* Show the error on the progress bar. A more generic error message - is going to be showed to user after this in the silc_connected. */ - purple_connection_update_progress(gc, buf, 2, 5); - } - - if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) { - SilcUInt32 err = SILC_PTR_TO_32(failure); - - if (err == SILC_AUTH_FAILED) - g_snprintf(buf, sizeof(buf), _("Failure: Authentication failed")); - - /* Show the error on the progress bar. A more generic error message - is going to be showed to user after this in the silc_connected. */ - purple_connection_update_progress(gc, buf, 4, 5); - } -} - -/* Asks whether the user would like to perform the key agreement protocol. - This is called after we have received an key agreement packet or an - reply to our key agreement packet. This returns TRUE if the user wants - the library to perform the key agreement protocol and FALSE if it is not - desired (application may start it later by calling the function - silc_client_perform_key_agreement). If TRUE is returned also the - `completion' and `context' arguments must be set by the application. */ - -static bool -silc_key_agreement(SilcClient client, SilcClientConnection conn, - SilcClientEntry client_entry, const char *hostname, - SilcUInt16 port, SilcKeyAgreementCallback *completion, - void **context) -{ - silcpurple_buddy_keyagr_request(client, conn, client_entry, hostname, port); - *completion = NULL; - *context = NULL; - return FALSE; -} - - -/* 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); -} - - -/* Delivers SILC session detachment data indicated by `detach_data' to the - application. If application has issued SILC_COMMAND_DETACH command - the client session in the SILC network is not quit. The client remains - in the network but is detached. The detachment data may be used later - to resume the session in the SILC Network. The appliation is - responsible of saving the `detach_data', to for example in a file. - - The detachment data can be given as argument to the functions - silc_client_connect_to_server, or silc_client_add_connection when - creating connection to remote server, inside SilcClientConnectionParams - structure. If it is provided the client library will attempt to resume - the session in the network. After the connection is created - successfully, the application is responsible of setting the user - interface for user into the same state it was before detaching (showing - same channels, channel modes, etc). It can do this by fetching the - information (like joined channels) from the client library. */ - -static void -silc_detach(SilcClient client, SilcClientConnection conn, - const unsigned char *detach_data, SilcUInt32 detach_data_len) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - const char *file; - - /* Save the detachment data to file. */ - file = silcpurple_session_file(purple_account_get_username(sg->account)); - g_unlink(file); - silc_file_writefile(file, (char *)detach_data, detach_data_len); -} - -SilcClientOperations ops = { - silc_say, - silc_channel_message, - silc_private_message, - silc_notify, - silc_command, - silc_command_reply, - silc_connected, - silc_disconnected, - silc_get_auth_method, - silc_verify_public_key, - silc_ask_passphrase, - silc_failure, - silc_key_agreement, - silc_ftp, - silc_detach -}; diff -r 0cc718e10344 -r 4f2d99bcb195 libpurple/protocols/silc10/pk.c --- a/libpurple/protocols/silc10/pk.c Mon Aug 22 06:32:44 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,274 +0,0 @@ -/* - - silcpurple_pk.c - - Author: Pekka Riikonen - - Copyright (C) 2004 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 "silcincludes.h" -#include "silcclient.h" -#include "silcpurple.h" - -/************************* Public Key Verification ***************************/ - -typedef struct { - SilcClient client; - SilcClientConnection conn; - char *filename; - char *entity; - char *entity_name; - char *fingerprint; - char *babbleprint; - unsigned char *pk; - SilcUInt32 pk_len; - SilcSKEPKType pk_type; - 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_data(verify->filename, verify->pk, - verify->pk_len, SILC_PKCS_FILE_PEM); - } - - silc_free(verify->filename); - silc_free(verify->entity); - silc_free(verify->entity_name); - silc_free(verify->fingerprint); - silc_free(verify->babbleprint); - silc_free(verify->pk); - 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) -{ - SilcPublicKey public_key; - PurpleConnection *gc = verify->client->application; - SilcPurple sg = gc->proto_data; - - silc_pkcs_public_key_decode(verify->pk, verify->pk_len, - &public_key); - silcpurple_show_public_key(sg, verify->entity_name, public_key, - G_CALLBACK(silcpurple_verify_details_cb), - verify); - silc_pkcs_public_key_free(public_key); -} - -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_connection_get_account(gc), entity, NULL, 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, SilcSocketType conn_type, - unsigned char *pk, SilcUInt32 pk_len, - SilcSKEPKType pk_type, - SilcVerifyPublicKey completion, void *context) -{ - PurpleConnection *gc = client->application; - int i; - char file[256], filename[256], filename2[256], *ipf, *hostf = NULL; - char *fingerprint, *babbleprint; - struct passwd *pw; - struct stat st; - char *entity = ((conn_type == SILC_SOCKET_TYPE_SERVER || - conn_type == SILC_SOCKET_TYPE_ROUTER) ? - "server" : "client"); - PublicKeyVerify verify; - - if (pk_type != SILC_SKE_PK_TYPE_SILC) { - purple_notify_error(gc, _("Verify Public Key"), - _("Unsupported public key type"), NULL); - 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)); - - if (conn_type == SILC_SOCKET_TYPE_SERVER || - conn_type == SILC_SOCKET_TYPE_ROUTER) { - if (!name) { - g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity, - conn->sock->ip, conn->sock->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, - conn->sock->hostname, conn->sock->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, conn->sock->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 = strdup(ipf); - verify->entity = strdup(entity); - verify->entity_name = (conn_type != SILC_SOCKET_TYPE_CLIENT ? - (name ? strdup(name) : strdup(conn->sock->hostname)) - : NULL); - verify->pk = silc_memdup(pk, pk_len); - verify->pk_len = pk_len; - verify->pk_type = pk_type; - 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, - SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(ipf, &public_key, - SILC_PKCS_FILE_BIN) && - (!hostf || (!silc_pkcs_load_public_key(hostf, &public_key, - SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(hostf, &public_key, - SILC_PKCS_FILE_BIN)))) { - 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); - silc_free(verify->filename); - silc_free(verify->entity); - silc_free(verify->entity_name); - silc_free(verify->pk); - silc_free(verify->fingerprint); - silc_free(verify->babbleprint); - silc_free(verify); - } -} diff -r 0cc718e10344 -r 4f2d99bcb195 libpurple/protocols/silc10/silc.c --- a/libpurple/protocols/silc10/silc.c Mon Aug 22 06:32:44 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1965 +0,0 @@ -/* - - silcpurple.c - - Author: Pekka Riikonen - - Copyright (C) 2004 - 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. - -*/ - -#include "silcincludes.h" -#include "silcclient.h" -#include "silcpurple.h" -#include "version.h" -#include "wb.h" -#include "core.h" - -extern SilcClientOperations ops; -static PurplePlugin *silc_plugin = NULL; - -static const char * -silcpurple_list_icon(PurpleAccount *a, PurpleBuddy *b) -{ - return (const char *)"silc"; -} - -static GList * -silcpurple_away_states(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(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 = gc->proto_data; - - 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 (!strcmp(state, "hyper")) - mode |= SILC_UMODE_HYPER; - else if (!strcmp(state, "away")) - mode |= SILC_UMODE_GONE; - else if (!strcmp(state, "busy")) - mode |= SILC_UMODE_BUSY; - else if (!strcmp(state, "indisposed")) - mode |= SILC_UMODE_INDISPOSED; - else if (!strcmp(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, - ++sg->conn->cmd_ident, 2, - 1, idp->data, idp->len, - 2, mb, sizeof(mb)); - silc_buffer_free(idp); -} - - -/*************************** Connection Routines *****************************/ - -static void -silcpurple_keepalive(PurpleConnection *gc) -{ - SilcPurple sg = gc->proto_data; - silc_client_send_packet(sg->client, sg->conn, SILC_PACKET_HEARTBEAT, - NULL, 0); -} - -static gboolean -silcpurple_scheduler(gpointer *context) -{ - SilcPurple sg = (SilcPurple)context; - silc_client_run_one(sg->client); - return TRUE; -} - -static void -silcpurple_nickname_parse(const char *nickname, - char **ret_nickname) -{ - silc_parse_userfqdn(nickname, ret_nickname, NULL); -} - -static void -silcpurple_login_connected(gpointer data, gint source, const gchar *error_message) -{ - PurpleConnection *gc = data; - SilcPurple sg; - SilcClient client; - SilcClientConnection conn; - PurpleAccount *account; - SilcClientConnectionParams params; - SilcUInt32 mask; - const char *dfile, *tmp; -#ifdef SILC_ATTRIBUTE_USER_ICON - PurpleStoredImage *img; -#endif -#ifdef HAVE_SYS_UTSNAME_H - struct utsname u; -#endif - - - g_return_if_fail(gc != NULL); - - sg = gc->proto_data; - - if (source < 0) { - purple_connection_error(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Connection failed")); - return; - } - - client = sg->client; - account = sg->account; - - /* 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; - - /* Add connection to SILC client library */ - conn = silc_client_add_connection( - sg->client, ¶ms, - (char *)purple_account_get_string(account, "server", - "silc.silcnet.org"), - purple_account_get_int(account, "port", 706), sg); - if (!conn) { - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Unable to initialize SILC Client connection")); - gc->proto_data = NULL; - return; - } - sg->conn = conn; - - /* Progress */ - if (params.detach_data) { - purple_connection_update_progress(gc, _("Resuming session"), 2, 5); - sg->resuming = TRUE; - } else { - purple_connection_update_progress(gc, _("Performing key exchange"), 2, 5); - } - - /* Perform SILC Key Exchange. The "silc_connected" will be called - eventually. */ - silc_client_start_key_exchange(sg->client, sg->conn, source); - - /* 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 -#ifdef _WIN32 - tmp = _tzname[0]; -#else - tmp = tzname[0]; -#endif - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_TIMEZONE, - (void *)tmp, strlen(tmp)); - -#ifdef SILC_ATTRIBUTE_USER_ICON - /* Set our buddy icon */ - img = purple_buddy_icons_find_account_icon(account); - silcpurple_buddy_set_icon(gc, img); - purple_imgstore_unref(img); -#endif - - silc_free(params.detach_data); -} - -static void -silcpurple_login(PurpleAccount *account) -{ - SilcPurple sg; - SilcClient client; - SilcClientParams params; - PurpleConnection *gc; - char pkd[256], prd[256]; - const char *cipher, *hmac; - char *realname; - int i; - - gc = account->gc; - if (!gc) - return; - gc->proto_data = NULL; - - memset(¶ms, 0, sizeof(params)); - strcat(params.nickname_format, "%n@%h%a"); - params.nickname_parse = silcpurple_nickname_parse; - params.ignore_requested_attributes = FALSE; - - /* 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)) { - const char *u = purple_account_get_username(account); - char **up = g_strsplit(u, "@", 2); - client->username = strdup(up[0]); - g_strfreev(up); - } else { - client->username = silc_get_username(); - purple_account_set_username(account, client->username); - } - realname = silc_get_real_name(); - if (purple_account_get_user_info(account)) { - client->realname = strdup(purple_account_get_user_info(account)); - free(realname); - } else if ((silc_get_real_name() != NULL) && (*realname != '\0')) { - client->realname = realname; - purple_account_set_user_info(account, client->realname); - } else { - free(realname); - client->realname = strdup(_("John Noname")); - } - client->hostname = silc_net_localhost(); - - purple_connection_set_display_name(gc, client->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 (!strcmp(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 (!strcmp(silc_default_hmacs[i].name, hmac)) { - silc_hmac_register(&(silc_default_hmacs[i])); - break; - } - - /* Init SILC client */ - if (!silc_client_init(client)) { - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, - _("Unable to initialize SILC protocol")); - return; - } - - /* 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")); - return; - } - - /* Progress */ - purple_connection_update_progress(gc, _("Connecting to SILC Server"), 1, 5); - - /* 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), - (gc->password == NULL) ? "" : gc->password, &client->pkcs, - &client->public_key, &client->private_key)) { - g_snprintf(pkd, sizeof(pkd), _("Unable to load SILC key pair: %s"), g_strerror(errno)); - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, - pkd); - return; - } - - sg = silc_calloc(1, sizeof(*sg)); - if (!sg) - return; - memset(sg, 0, sizeof(*sg)); - sg->client = client; - sg->gc = gc; - sg->account = account; - gc->proto_data = sg; - - /* Connect to the SILC server */ - if (purple_proxy_connect(gc, account, - purple_account_get_string(account, "server", - "silc.silcnet.org"), - purple_account_get_int(account, "port", 706), - silcpurple_login_connected, gc) == NULL) - { - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Unable to create connection")); - return; - } - - /* Schedule SILC using Glib's event loop */ - sg->scheduler = purple_timeout_add(300, (GSourceFunc)silcpurple_scheduler, sg); -} - -static int -silcpurple_close_final(gpointer *context) -{ - SilcPurple sg = (SilcPurple)context; - silc_client_stop(sg->client); - silc_client_free(sg->client); -#ifdef HAVE_SILCMIME_H - if (sg->mimeass) - silc_mime_assembler_free(sg->mimeass); -#endif - silc_free(sg); - return 0; -} - -static void -silcpurple_close(PurpleConnection *gc) -{ - SilcPurple sg = gc->proto_data; - GHashTable *ui_info; - const char *ui_name = NULL, *ui_website = NULL; - char *quit_msg; - - g_return_if_fail(sg != NULL); - - ui_info = purple_core_get_ui_info(); - - if(ui_info) { - ui_name = g_hash_table_lookup(ui_info, "name"); - ui_website = g_hash_table_lookup(ui_info, "website"); - } - - if(!ui_name || !ui_website) { - ui_name = "Pidgin"; - ui_website = PURPLE_WEBSITE; - } - quit_msg = g_strdup_printf(_("Download %s: %s"), - ui_name, ui_website); - - /* 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); - - purple_timeout_remove(sg->scheduler); - purple_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 = gc->proto_data; - 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 = gc->proto_data; - 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(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - 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; - gboolean device = TRUE; - char status[1024]; - - sg = gc->proto_data; - if (!sg) - return; - - 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)); - - if (!silc_hash_table_find(attrs, - SILC_32_TO_PTR(SILC_ATTRIBUTE_DEVICE_INFO), - NULL, (void *)&attr)) - device = FALSE; - } - - 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); -#if 0 - f = purple_request_field_label_new("l2", _("Online Services")); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("services", - _("Let others see what services you are using"), - TRUE); - purple_request_field_group_add_field(g, f); -#endif -#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); -#ifdef _WIN32 - f = purple_request_field_string_new("timezone", _("Timezone"), _tzname[0], FALSE); -#else - f = purple_request_field_string_new("timezone", _("Timezone"), tzname[0], FALSE); -#endif - 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), - gc->account, NULL, NULL, gc); -} - -static void -silcpurple_detach(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - SilcPurple sg; - - if (!gc) - return; - sg = gc->proto_data; - if (!sg) - return; - - /* Call DETACH */ - silc_client_command_call(sg->client, sg->conn, "DETACH"); - sg->detaching = TRUE; -} - -static void -silcpurple_view_motd(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - SilcPurple sg; - char *tmp; - - if (!gc) - return; - sg = gc->proto_data; - if (!sg) - return; - - if (!sg->motd) { - purple_notify_error( - gc, _("Message of the Day"), _("No Message of the Day available"), - _("There is no Message of the Day associated with this connection")); - return; - } - - tmp = g_markup_escape_text(sg->motd, -1); - purple_notify_formatted(gc, 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 = gc->proto_data; - 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 = gc->proto_data; - 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 (strcmp(pass1, pass2)) { - purple_notify_error( - gc, _("Create New SILC Key Pair"), _("Passphrases do not match"), NULL); - 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_encode_identifier((char *)un, (char *)hn, - (char *)rn, (char *)e, (char *)o, (char *)c); - - /* Create the key pair */ - if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS, keylen, pkfile, prfile, - identifier, pass1, NULL, &public_key, NULL, - FALSE)) { - purple_notify_error( - gc, _("Create New SILC Key Pair"), _("Key Pair Generation failed"), NULL); - 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(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - SilcPurple sg = gc->proto_data; - PurpleRequestFields *fields; - PurpleRequestFieldGroup *g; - PurpleRequestField *f; - const char *username, *realname; - char *hostname, **u; - char tmp[256], pkd[256], pkd2[256], prd[256], prd2[256]; - - username = purple_account_get_username(sg->account); - u = g_strsplit(username, "@", 2); - username = u[0]; - realname = purple_account_get_user_info(sg->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(gc->account, "public-key", pkd2)); - g_snprintf(prd, sizeof(prd) - 1, "%s", - purple_account_get_string(gc->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(gc, _("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), - gc->account, NULL, NULL, gc); - - g_strfreev(u); - silc_free(hostname); -} - -static void -silcpurple_change_pass(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - purple_account_request_change_password(purple_connection_get_account(gc)); -} - -static void -silcpurple_change_passwd(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(gc->account, - "private-key", - prd), old ? old : "", new ? new : ""); -} - -static void -silcpurple_show_set_info(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - purple_account_request_change_user_info(purple_connection_get_account(gc)); -} - -static void -silcpurple_set_info(PurpleConnection *gc, const char *text) -{ -} - -static GList * -silcpurple_actions(PurplePlugin *plugin, gpointer context) -{ - GList *list = NULL; - PurplePluginAction *act; - - act = purple_plugin_action_new(_("Online Status"), - silcpurple_attrs); - list = g_list_append(list, act); - - act = purple_plugin_action_new(_("Detach From Server"), - silcpurple_detach); - list = g_list_append(list, act); - - act = purple_plugin_action_new(_("View Message of the Day"), - silcpurple_view_motd); - list = g_list_append(list, act); - - act = purple_plugin_action_new(_("Create SILC Key Pair..."), - silcpurple_create_keypair); - list = g_list_append(list, act); - - act = purple_plugin_action_new(_("Change Password..."), - silcpurple_change_pass); - list = g_list_append(list, act); - - act = purple_plugin_action_new(_("Set User Info..."), - silcpurple_show_set_info); - list = g_list_append(list, act); - - return list; -} - - -/******************************* 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, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - SilcPurpleIM im = context; - PurpleConversation *convo; - char tmp[256], *nickname = NULL; - SilcClientEntry client_entry; -#ifdef HAVE_SILCMIME_H - SilcDList list; -#endif - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, im->nick, - sg->account); - if (!convo) - return; - - if (!clients) - goto err; - - if (clients_count > 1) { - silc_parse_userfqdn(im->nick, &nickname, NULL); - - /* 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, - nickname, im->nick, - &clients_count); - if (!clients) - goto err; - client_entry = clients[0]; - silc_free(clients); - } else { - client_entry = clients[0]; - } - -#ifdef HAVE_SILCMIME_H - /* Check for images */ - if (im->gflags & PURPLE_MESSAGE_IMAGES) { - list = silcpurple_image_message(im->message, (SilcUInt32 *)&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, - buf->data, buf->len, - TRUE); - silc_mime_partial_free(list); - purple_conv_im_write(PURPLE_CONV_IM(convo), conn->local_entry->nickname, - im->message, 0, time(NULL)); - goto out; - } - } -#endif - - /* Send the message */ - silc_client_send_private_message(client, conn, client_entry, im->flags, - (unsigned char *)im->message, im->message_len, TRUE); - purple_conv_im_write(PURPLE_CONV_IM(convo), conn->local_entry->nickname, - im->message, 0, time(NULL)); - goto out; - - err: - g_snprintf(tmp, sizeof(tmp), - _("User %s is not present in the network"), im->nick); - purple_conversation_write(convo, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); - - out: - g_free(im->nick); - g_free(im->message); - silc_free(im); - silc_free(nickname); -} - -static int -silcpurple_send_im(PurpleConnection *gc, const char *who, const char *message, - PurpleMessageFlags flags) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcClientEntry *clients; - SilcUInt32 clients_count, mflags; - char *nickname, *msg, *tmp; - int ret = 0; - gboolean sign = purple_account_get_bool(sg->account, "sign-verify", FALSE); -#ifdef HAVE_SILCMIME_H - SilcDList list; -#endif - - if (!who || !message) - 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")); - g_free(tmp); - return 0; - } - - - if (!silc_parse_userfqdn(who, &nickname, NULL)) { - g_free(tmp); - return 0; - } - - if (sign) - mflags |= SILC_MESSAGE_FLAG_SIGNED; - - /* Find client entry */ - clients = silc_client_get_clients_local(client, conn, nickname, who, - &clients_count); - if (!clients) { - /* Resolve unknown user */ - SilcPurpleIM im = silc_calloc(1, sizeof(*im)); - if (!im) { - g_free(tmp); - return 0; - } - im->nick = g_strdup(who); - im->message = g_strdup(message); - im->message_len = strlen(im->message); - im->flags = mflags; - im->gflags = flags; - silc_client_get_clients(client, conn, nickname, NULL, - silcpurple_send_im_resolved, im); - silc_free(nickname); - g_free(tmp); - return 0; - } - -#ifdef HAVE_SILCMIME_H - /* 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, - clients[0], mflags, - buf->data, buf->len, - TRUE); - silc_mime_partial_free(list); - g_free(tmp); - silc_free(nickname); - silc_free(clients); - return ret; - } - } -#endif - - /* Send private message directly */ - ret = silc_client_send_private_message(client, conn, clients[0], - mflags, - (unsigned char *)msg, - strlen(msg), TRUE); - - g_free(tmp); - silc_free(nickname); - silc_free(clients); - return ret; -} - - -static GList *silcpurple_blist_node_menu(PurpleBlistNode *node) { - /* split this single menu building function back into the two - original: one for buddies and one for chats */ - - if(PURPLE_BLIST_NODE_IS_CHAT(node)) { - return silcpurple_chat_menu((PurpleChat *) node); - } else if(PURPLE_BLIST_NODE_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 *convo = conv; - int id = 0; - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - if(args && args[0]) - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, args[0], - gc->account); - - if (convo != NULL) - id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)); - - if (id == 0) - return PURPLE_CMD_RET_FAILED; - - silcpurple_chat_leave(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_gc(conv); - id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)); - - if (gc == NULL || id == 0) - return PURPLE_CMD_RET_FAILED; - - if (!args || !args[0]) { - topic = purple_conv_chat_get_topic (PURPLE_CONV_CHAT(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_conv_chat_write(PURPLE_CONV_CHAT(conv), gc->account->username, buf, - PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); - 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(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(purple_conversation_get_gc(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_gc(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_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - silcpurple_get_info(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; - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - ret = silcpurple_send_im(gc, args[0], args[1], PURPLE_MESSAGE_SEND); - - 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 *convo; - 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_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - account = purple_connection_get_account(gc); - - convo = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, args[0]); - - if (args[1]) { - ret = silcpurple_send_im(gc, args[0], args[1], PURPLE_MESSAGE_SEND); - purple_conv_im_write(PURPLE_CONV_IM(convo), purple_connection_get_display_name(gc), - args[1], PURPLE_MESSAGE_SEND, time(NULL)); - } - - 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_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = gc->proto_data; - - 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_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = gc->proto_data; - - 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_gc(conv); - - if (gc == NULL || !args || gc->proto_data == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = gc->proto_data; - - 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_conv_chat_write(PURPLE_CONV_CHAT(conv), "", - msg, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); - g_free(msg); - return PURPLE_CMD_RET_OK; - } - - 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(_("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_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = gc->proto_data; - - 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; - GHashTable *ui_info; - const char *ui_name = NULL, *ui_website = NULL; - char *quit_msg; - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = gc->proto_data; - - if (sg == NULL) - return PURPLE_CMD_RET_FAILED; - - ui_info = purple_core_get_ui_info(); - - if(ui_info) { - ui_name = g_hash_table_lookup(ui_info, "name"); - ui_website = g_hash_table_lookup(ui_info, "website"); - } - - if(!ui_name || !ui_website) { - ui_name = "Pidgin"; - ui_website = PURPLE_WEBSITE; - } - quit_msg = g_strdup_printf(_("Download %s: %s"), - ui_name, ui_website); - - silc_client_command_call(sg->client, sg->conn, NULL, - "QUIT", (args && args[0]) ? args[0] : 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_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = gc->proto_data; - - 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) -{ - purple_cmd_register("part", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, - "prpl-silc", silcpurple_cmd_chat_part, _("part [channel]: Leave the chat"), NULL); - purple_cmd_register("leave", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, - "prpl-silc", silcpurple_cmd_chat_part, _("leave [channel]: Leave the chat"), NULL); - purple_cmd_register("topic", "s", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", - silcpurple_cmd_chat_topic, _("topic [<new topic>]: View or change the topic"), NULL); - purple_cmd_register("join", "ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, - "prpl-silc", silcpurple_cmd_chat_join, - _("join <channel> [<password>]: Join a chat on this network"), NULL); - purple_cmd_register("list", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", - silcpurple_cmd_chat_list, _("list: List channels on this network"), NULL); - purple_cmd_register("whois", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", - silcpurple_cmd_whois, _("whois <nick>: View nick's information"), NULL); - purple_cmd_register("msg", "ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_msg, - _("msg <nick> <message>: Send a private message to a user"), NULL); - purple_cmd_register("query", "ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_query, - _("query <nick> [<message>]: Send a private message to a user"), NULL); - purple_cmd_register("motd", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_motd, - _("motd: View the server's Message Of The Day"), NULL); - purple_cmd_register("detach", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_detach, - _("detach: Detach this session"), NULL); - purple_cmd_register("quit", "s", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_quit, - _("quit [message]: Disconnect from the server, with an optional message"), NULL); - purple_cmd_register("call", "s", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_call, - _("call <command>: Call any silc client command"), NULL); - /* These below just get passed through for the silc client library to deal - * with */ - purple_cmd_register("kill", "ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("kill <nick> [-pubkey|<reason>]: Kill nick"), NULL); - purple_cmd_register("nick", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("nick <newnick>: Change your nickname"), NULL); - purple_cmd_register("whowas", "ww", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("whowas <nick>: View nick's information"), NULL); - purple_cmd_register("cmode", "wws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_cmode, - _("cmode <channel> [+|-<modes>] [arguments]: Change or display channel modes"), NULL); - purple_cmd_register("cumode", "wws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("cumode <channel> +|-<modes> <nick>: Change nick's modes on channel"), NULL); - purple_cmd_register("umode", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("umode <usermodes>: Set your modes in the network"), NULL); - purple_cmd_register("oper", "s", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("oper <nick> [-pubkey]: Get server operator privileges"), NULL); - purple_cmd_register("invite", "ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_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); - purple_cmd_register("kick", "wws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("kick <channel> <nick> [comment]: Kick client from channel"), NULL); - purple_cmd_register("info", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("info [server]: View server administrative details"), NULL); - purple_cmd_register("ban", "ww", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("ban [<channel> +|-<nick>]: Ban client from channel"), NULL); - purple_cmd_register("getkey", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("getkey <nick|server>: Retrieve client's or server's public key"), NULL); - purple_cmd_register("stats", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("stats: View server and network statistics"), NULL); - purple_cmd_register("ping", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("ping: Send PING to the connected server"), NULL); -#if 0 /* Purple doesn't handle these yet */ - purple_cmd_register("users", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_users, - _("users <channel>: List users in channel")); - purple_cmd_register("names", "ww", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_names, - _("names [-count|-ops|-halfops|-voices|-normal] <channel(s)>: List specific users in channel(s)")); -#endif -} - -static PurpleWhiteboardPrplOps 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 PurplePluginProtocolInfo prpl_info = -{ -#ifdef HAVE_SILCMIME_H - OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | - OPT_PROTO_PASSWORD_OPTIONAL | OPT_PROTO_IM_IMAGE | - OPT_PROTO_SLASH_COMMANDS_NATIVE, -#else - OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | - OPT_PROTO_PASSWORD_OPTIONAL | - OPT_PROTO_SLASH_COMMANDS_NATIVE, -#endif - NULL, /* user_splits */ - NULL, /* protocol_options */ -#ifdef SILC_ATTRIBUTE_USER_ICON - {"jpeg,gif,png,bmp", 0, 0, 96, 96, 0, PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */ -#else - NO_BUDDY_ICONS, -#endif - silcpurple_list_icon, /* list_icon */ - NULL, /* list_emblems */ - silcpurple_status_text, /* status_text */ - silcpurple_tooltip_text, /* tooltip_text */ - silcpurple_away_states, /* away_states */ - silcpurple_blist_node_menu, /* blist_node_menu */ - silcpurple_chat_info, /* chat_info */ - silcpurple_chat_info_defaults,/* chat_info_defaults */ - silcpurple_login, /* login */ - silcpurple_close, /* close */ - silcpurple_send_im, /* send_im */ - silcpurple_set_info, /* set_info */ - NULL, /* send_typing */ - silcpurple_get_info, /* get_info */ - silcpurple_set_status, /* set_status */ - silcpurple_idle_set, /* set_idle */ - silcpurple_change_passwd, /* change_passwd */ - silcpurple_add_buddy, /* add_buddy */ - NULL, /* add_buddies */ - silcpurple_remove_buddy, /* remove_buddy */ - NULL, /* remove_buddies */ - NULL, /* add_permit */ - NULL, /* add_deny */ - NULL, /* rem_permit */ - NULL, /* rem_deny */ - NULL, /* set_permit_deny */ - silcpurple_chat_join, /* join_chat */ - NULL, /* reject_chat */ - silcpurple_get_chat_name, /* get_chat_name */ - silcpurple_chat_invite, /* chat_invite */ - silcpurple_chat_leave, /* chat_leave */ - NULL, /* chat_whisper */ - silcpurple_chat_send, /* chat_send */ - silcpurple_keepalive, /* keepalive */ - NULL, /* register_user */ - NULL, /* get_cb_info */ - NULL, /* get_cb_away */ - NULL, /* alias_buddy */ - NULL, /* group_buddy */ - NULL, /* rename_group */ - NULL, /* buddy_free */ - NULL, /* convo_closed */ - NULL, /* normalize */ -#ifdef SILC_ATTRIBUTE_USER_ICON - silcpurple_buddy_set_icon, /* set_buddy_icon */ -#else - NULL, -#endif - NULL, /* remove_group */ - NULL, /* get_cb_real_name */ - silcpurple_chat_set_topic, /* set_chat_topic */ - NULL, /* find_blist_chat */ - silcpurple_roomlist_get_list, /* roomlist_get_list */ - silcpurple_roomlist_cancel, /* roomlist_cancel */ - NULL, /* roomlist_expand_category */ - NULL, /* can_receive_file */ - silcpurple_ftp_send_file, /* send_file */ - silcpurple_ftp_new_xfer, /* new_xfer */ - NULL, /* offline_message */ - &silcpurple_wb_ops, /* whiteboard_prpl_ops */ - NULL, /* send_raw */ - NULL, /* roomlist_room_serialize */ - NULL, /* unregister_user */ - NULL, /* send_attention */ - NULL, /* get_attention_types */ - sizeof(PurplePluginProtocolInfo), /* struct_size */ - NULL, /* get_account_text_table */ - NULL, /* initiate_media */ - NULL, /* get_media_caps */ - NULL, /* get_moods */ - NULL, /* set_public_alias */ - NULL, /* get_public_alias */ - NULL, /* add_buddy_with_invite */ - NULL /* add_buddies_with_invite */ -}; - -static PurplePluginInfo info = -{ - PURPLE_PLUGIN_MAGIC, - PURPLE_MAJOR_VERSION, - PURPLE_MINOR_VERSION, - PURPLE_PLUGIN_PROTOCOL, /**< type */ - NULL, /**< ui_requirement */ - 0, /**< flags */ - NULL, /**< dependencies */ - PURPLE_PRIORITY_DEFAULT, /**< priority */ - - "prpl-silc", /**< id */ - "SILC", /**< name */ - "1.0", /**< version */ - /** summary */ - N_("SILC Protocol Plugin"), - /** description */ - N_("Secure Internet Live Conferencing (SILC) Protocol"), - "Pekka Riikonen", /**< author */ - "http://silcnet.org/", /**< homepage */ - - NULL, /**< load */ - NULL, /**< unload */ - NULL, /**< destroy */ - - NULL, /**< ui_info */ - &prpl_info, /**< extra_info */ - NULL, /**< prefs_info */ - silcpurple_actions, - - /* padding */ - NULL, - NULL, - NULL, - NULL -}; - -static void -init_plugin(PurplePlugin *plugin) -{ - PurpleAccountOption *option; - PurpleAccountUserSplit *split; - char tmp[256]; - int i; - PurpleKeyValuePair *kvp; - GList *list = NULL; - - silc_plugin = plugin; - - split = purple_account_user_split_new(_("Network"), "silcnet.org", '@'); - prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); - - /* Account options */ - option = purple_account_option_string_new(_("Connect server"), - "server", - "silc.silcnet.org"); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - option = purple_account_option_int_new(_("Port"), "port", 706); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_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); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_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); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - for (i = 0; silc_default_ciphers[i].name; i++) { - kvp = g_new0(PurpleKeyValuePair, 1); - kvp->key = g_strdup(silc_default_ciphers[i].name); - kvp->value = g_strdup(silc_default_ciphers[i].name); - list = g_list_append(list, kvp); - } - option = purple_account_option_list_new(_("Cipher"), "cipher", list); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - list = NULL; - for (i = 0; silc_default_hmacs[i].name; i++) { - kvp = g_new0(PurpleKeyValuePair, 1); - kvp->key = g_strdup(silc_default_hmacs[i].name); - kvp->value = g_strdup(silc_default_hmacs[i].name); - list = g_list_append(list, kvp); - } - option = purple_account_option_list_new(_("HMAC"), "hmac", list); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - option = purple_account_option_bool_new(_("Public key authentication"), - "pubkey-auth", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - option = purple_account_option_bool_new(_("Block IMs without Key Exchange"), - "block-ims", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - option = purple_account_option_bool_new(_("Block messages to whiteboard"), - "block-wb", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - option = purple_account_option_bool_new(_("Automatically open whiteboard"), - "open-wb", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - option = purple_account_option_bool_new(_("Digitally sign and verify all messages"), - "sign-verify", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - purple_prefs_remove("/plugins/prpl/silc"); - - silcpurple_register_commands(); - -#ifdef _WIN32 - silc_net_win32_init(); -#endif -} - -PURPLE_INIT_PLUGIN(silc10, init_plugin, info); diff -r 0cc718e10344 -r 4f2d99bcb195 libpurple/protocols/silc10/silcpurple.h --- a/libpurple/protocols/silc10/silcpurple.h Mon Aug 22 06:32:44 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,173 +0,0 @@ -/* - - silcpurple.h - - Author: Pekka Riikonen - - Copyright (C) 2004 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 SILCPURPLE_H -#define SILCPURPLE_H - -/* Purple includes */ -#include "internal.h" -#include "account.h" -#include "accountopt.h" -#include "cmds.h" -#include "conversation.h" -#include "debug.h" -#include "ft.h" -#include "notify.h" -#include "prpl.h" -#include "request.h" -#include "roomlist.h" -#include "server.h" -#include "util.h" - -/* 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 { - SilcClient client; - SilcClientConnection conn; - - guint scheduler; - PurpleConnection *gc; - PurpleAccount *account; - unsigned long channel_ids; - GList *grps; - - char *motd; - PurpleRoomlist *roomlist; -#ifdef HAVE_SILCMIME_H - SilcMimeAssembler mimeass; -#endif - unsigned int detaching : 1; - unsigned int resuming : 1; - unsigned int roomlist_cancelled : 1; - unsigned int chpk : 1; -} *SilcPurple; - - -gboolean silcpurple_check_silc_dir(PurpleConnection *gc); -void silcpurple_chat_join_done(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context); -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, SilcSocketType conn_type, - unsigned char *pk, SilcUInt32 pk_len, - SilcSKEPKType pk_type, - SilcVerifyPublicKey completion, void *context); -GList *silcpurple_buddy_menu(PurpleBuddy *buddy); -void silcpurple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group); -void silcpurple_send_buddylist(PurpleConnection *gc); -void silcpurple_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group); -void silcpurple_buddy_keyagr_request(SilcClient client, - SilcClientConnection conn, - SilcClientEntry client_entry, - const char *hostname, SilcUInt16 port); -void silcpurple_idle_set(PurpleConnection *gc, int idle); -void silcpurple_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full); -char *silcpurple_status_text(PurpleBuddy *b); -gboolean silcpurple_ip_is_private(const char *ip); -void silcpurple_ftp_send_file(PurpleConnection *gc, const char *name, const char *file); -PurpleXfer *silcpurple_ftp_new_xfer(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(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(PurpleConnection *gc); -GHashTable *silcpurple_chat_info_defaults(PurpleConnection *gc, const char *chat_name); -GList *silcpurple_chat_menu(PurpleChat *); -void silcpurple_chat_join(PurpleConnection *gc, GHashTable *data); -char *silcpurple_get_chat_name(GHashTable *data); -void silcpurple_chat_invite(PurpleConnection *gc, int id, const char *msg, - const char *name); -void silcpurple_chat_leave(PurpleConnection *gc, int id); -int silcpurple_chat_send(PurpleConnection *gc, int id, const char *msg, PurpleMessageFlags flags); -void silcpurple_chat_set_topic(PurpleConnection *gc, int id, const char *topic); -PurpleRoomlist *silcpurple_roomlist_get_list(PurpleConnection *gc); -void silcpurple_roomlist_cancel(PurpleRoomlist *list); -void silcpurple_chat_chauth_show(SilcPurple sg, SilcChannelEntry channel, - SilcBuffer channel_pubkeys); -void silcpurple_parse_attrs(SilcDList attrs, char **moodstr, char **statusstr, - char **contactstr, char **langstr, char **devicestr, - char **tzstr, char **geostr); -#ifdef SILC_ATTRIBUTE_USER_ICON -void silcpurple_buddy_set_icon(PurpleConnection *gc, PurpleStoredImage *img); -#endif -#ifdef HAVE_SILCMIME_H -char *silcpurple_file2mime(const char *filename); -SilcDList silcpurple_image_message(const char *msg, SilcUInt32 *mflags); -#endif - -#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 /* SILCPURPLE_H */ diff -r 0cc718e10344 -r 4f2d99bcb195 libpurple/protocols/silc10/util.c --- a/libpurple/protocols/silc10/util.c Mon Aug 22 06:32:44 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,776 +0,0 @@ -/* - - silcpurple_util.c - - Author: Pekka Riikonen - - Copyright (C) 2004 - 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. - -*/ - -#include "silcincludes.h" -#include "silcclient.h" -#include "silcpurple.h" -#include "imgstore.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; -} - -/* 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]; - struct stat 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()); - - /* - * Check ~/.silc directory - */ - if ((g_stat(filename, &st)) == -1) { - /* If dir doesn't exist */ - if (errno == ENOENT) { - if (pw->pw_uid == geteuid()) { - if ((g_mkdir(filename, 0755)) == -1) { - purple_debug_error("silc", "Couldn't create '%s' directory\n", filename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n", - filename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n", filename, g_strerror(errno)); - return FALSE; - } - } else { -#ifndef _WIN32 - /* 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_stat(servfilename, &st)) == -1) { - /* If dir doesn't exist */ - if (errno == ENOENT) { - if (pw->pw_uid == geteuid()) { - if ((g_mkdir(servfilename, 0755)) == -1) { - purple_debug_error("silc", "Couldn't create '%s' directory\n", servfilename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n", - servfilename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n", - servfilename, g_strerror(errno)); - return FALSE; - } - } - - /* - * Check ~./silc/clientkeys directory - */ - if ((g_stat(clientfilename, &st)) == -1) { - /* If dir doesn't exist */ - if (errno == ENOENT) { - if (pw->pw_uid == geteuid()) { - if ((g_mkdir(clientfilename, 0755)) == -1) { - purple_debug_error("silc", "Couldn't create '%s' directory\n", clientfilename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n", - clientfilename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n", - clientfilename, g_strerror(errno)); - return FALSE; - } - } - - /* - * Check ~./silc/friends directory - */ - if ((g_stat(friendsfilename, &st)) == -1) { - /* If dir doesn't exist */ - if (errno == ENOENT) { - if (pw->pw_uid == geteuid()) { - if ((g_mkdir(friendsfilename, 0755)) == -1) { - purple_debug_error("silc", "Couldn't create '%s' directory\n", friendsfilename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n", - friendsfilename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n", - friendsfilename, g_strerror(errno)); - 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(gc->account, "public-key", pkd)); - g_snprintf(file_private_key, sizeof(file_public_key) - 1, "%s", - purple_account_get_string(gc->account, "private-key", prd)); - - if ((g_stat(file_public_key, &st)) == -1) { - /* If file doesn't exist */ - if (errno == ENOENT) { - purple_connection_update_progress(gc, _("Creating SILC key pair..."), 1, 5); - if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS, - SILCPURPLE_DEF_PKCS_LEN, - file_public_key, file_private_key, NULL, - (gc->password == NULL) ? "" : gc->password, - NULL, NULL, NULL, FALSE)) { - purple_debug_error("silc", "Couldn't create key pair\n"); - 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 ((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 ((g_stat(file_private_key, &st)) == -1) { - /* If file doesn't exist */ - if (errno == ENOENT) { - purple_connection_update_progress(gc, _("Creating SILC key pair..."), 1, 5); - if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS, - SILCPURPLE_DEF_PKCS_LEN, - file_public_key, file_private_key, NULL, - (gc->password == NULL) ? "" : gc->password, - NULL, NULL, NULL, FALSE)) { - purple_debug_error("silc", "Couldn't create key pair\n"); - return FALSE; - } - - if ((fd = g_open(file_private_key, O_RDONLY, 0)) != -1) { - if ((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; - } - } - /* This shouldn't really happen because silc_create_key_pair() - * will set the permissions */ - else if ((g_stat(file_private_key, &st)) == -1) { - purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n", - file_private_key, g_strerror(errno)); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't stat '%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); - - 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; - SilcPKCS pkcs; - char *fingerprint, *babbleprint; - unsigned char *pk; - SilcUInt32 pk_len, key_len = 0; - GString *s; - char *buf; - - ident = silc_pkcs_decode_identifier(public_key->identifier); - if (!ident) - return; - - pk = silc_pkcs_public_key_encode(public_key, &pk_len); - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - - if (silc_pkcs_alloc((unsigned char *)public_key->name, &pkcs)) { - key_len = silc_pkcs_public_key_set(pkcs, public_key); - silc_pkcs_free(pkcs); - } - - 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"), public_key->name); - g_string_append_printf(s, _("Key Length: \t%d bits\n"), (int)key_len); - 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); - - buf = g_string_free(s, FALSE); - - purple_request_action(sg->gc, _("Public Key Information"), - _("Public Key Information"), - buf, 0, purple_connection_get_account(sg->gc), - NULL, NULL, context, 1, _("Close"), callback); - - g_free(buf); - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); - silc_pkcs_free_identifier(ident); -} - -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 (strlen(s->str)) { - *moodstr = s->str; - 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 (strlen(s->str)) { - *contactstr = s->str; - 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 (strlen(s->str)) { - *devicestr = s->str; - 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 : ""); -} - -#ifdef HAVE_SILCMIME_H -/* Returns MIME type of filetype */ - -char *silcpurple_file2mime(const char *filename) -{ - const char *ct; - - ct = strrchr(filename, '.'); - if (!ct) - return NULL; - else if (!g_ascii_strcasecmp(".png", ct)) - return strdup("image/png"); - else if (!g_ascii_strcasecmp(".jpg", ct)) - return strdup("image/jpeg"); - else if (!g_ascii_strcasecmp(".jpeg", ct)) - return strdup("image/jpeg"); - else if (!g_ascii_strcasecmp(".gif", ct)) - return strdup("image/gif"); - else if (!g_ascii_strcasecmp(".tiff", ct)) - return strdup("image/tiff"); - - return NULL; -} - -/* 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, SilcUInt32 *mflags) -{ - SilcMime mime = NULL, p; - SilcDList list, parts = NULL; - const char *start, *end, *last; - GData *attribs; - char *type; - gboolean images = FALSE; - - last = msg; - while (last && *last && purple_markup_find_tag("img", last, &start, - &end, &attribs)) { - PurpleStoredImage *image = NULL; - const char *id; - - /* 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, (unsigned char *)text, strlen(text)); - g_free(text); - - if (!parts) - parts = silc_dlist_init(); - silc_dlist_add(parts, p); - } - - id = g_datalist_get_data(&attribs, "id"); - if (id && (image = purple_imgstore_find_by_id(atoi(id)))) { - unsigned long imglen = purple_imgstore_get_size(image); - gconstpointer img = purple_imgstore_get_data(image); - - p = silc_mime_alloc(); - - /* Add content type */ - type = silcpurple_file2mime(purple_imgstore_get_filename(image)); - if (!type) { - g_datalist_clear(&attribs); - last = end + 1; - continue; - } - silc_mime_add_field(p, "Content-Type", type); - silc_free(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, (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; -} - -#endif /* HAVE_SILCMIME_H */ diff -r 0cc718e10344 -r 4f2d99bcb195 libpurple/protocols/silc10/wb.c --- a/libpurple/protocols/silc10/wb.c Mon Aug 22 06:32:44 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,520 +0,0 @@ -/* - - wb.c - - Author: Pekka Riikonen - - 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. - -*/ - -#include "silcincludes.h" -#include "silcclient.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) -{ - SilcClientConnection conn; - PurpleWhiteboard *wb; - SilcPurpleWb wbs; - - conn = sg->conn; - wb = purple_whiteboard_get_session(sg->account, client_entry->nickname); - if (!wb) - wb = purple_whiteboard_create(sg->account, client_entry->nickname, 0); - if (!wb) - return NULL; - - if (!wb->proto_data) { - 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; - wb->proto_data = wbs; - - /* Start the whiteboard */ - purple_whiteboard_start(wb); - purple_whiteboard_clear(wb); - } - - return wb; -} - -PurpleWhiteboard *silcpurple_wb_init_ch(SilcPurple sg, SilcChannelEntry channel) -{ - PurpleWhiteboard *wb; - SilcPurpleWb wbs; - - wb = purple_whiteboard_get_session(sg->account, channel->channel_name); - if (!wb) - wb = purple_whiteboard_create(sg->account, channel->channel_name, 0); - if (!wb) - return NULL; - - if (!wb->proto_data) { - 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; - wb->proto_data = wbs; - - /* Start the whiteboard */ - purple_whiteboard_start(wb); - purple_whiteboard_clear(wb); - } - - return wb; -} - -static void -silcpurple_wb_parse(SilcPurpleWb wbs, PurpleWhiteboard *wb, - unsigned char *message, SilcUInt32 message_len) -{ - 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, height, width); - - 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 (buf.len > 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->proto_data, 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[128]; - SilcPurpleWbRequest req; - PurpleConnection *gc; - SilcPurple sg; - - gc = client->application; - sg = gc->proto_data; - - /* 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->proto_data, 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(sender, _("Whiteboard"), tmp, NULL, 1, - sg->account, sender->nickname, NULL, 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) -{ - SilcPurple sg; - PurpleConnection *gc; - PurpleWhiteboard *wb; - SilcPurpleWb wbs; - - gc = client->application; - sg = gc->proto_data; - - wb = purple_whiteboard_get_session(sg->account, sender->nickname); - if (!wb) { - /* Ask user if they want to open the whiteboard */ - silcpurple_wb_request(client, message, message_len, - sender, NULL); - return; - } - - wbs = wb->proto_data; - silcpurple_wb_parse(wbs, 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) -{ - SilcPurple sg; - PurpleConnection *gc; - PurpleWhiteboard *wb; - SilcPurpleWb wbs; - - gc = client->application; - sg = gc->proto_data; - - wb = purple_whiteboard_get_session(sg->account, channel->channel_name); - if (!wb) { - /* Ask user if they want to open the whiteboard */ - silcpurple_wb_request(client, message, message_len, - sender, channel); - return; - } - - wbs = wb->proto_data; - silcpurple_wb_parse(wbs, wb, (unsigned char *)message, message_len); -} - -/* Send whiteboard message */ - -void silcpurple_wb_send(PurpleWhiteboard *wb, GList *draw_list) -{ - SilcPurpleWb wbs = wb->proto_data; - SilcBuffer packet; - GList *list; - int len; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(draw_list); - gc = purple_account_get_connection(wb->account); - g_return_if_fail(gc); - sg = gc->proto_data; - 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, - packet->head, len, TRUE); - } 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, - packet->head, len, TRUE); - } - - 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) -{ - silc_free(wb->proto_data); - wb->proto_data = NULL; -} - -void silcpurple_wb_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height) -{ - SilcPurpleWb wbs = wb->proto_data; - *width = wbs->width; - *height = wbs->height; -} - -void silcpurple_wb_set_dimensions(PurpleWhiteboard *wb, int width, int height) -{ - SilcPurpleWb wbs = wb->proto_data; - 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 = wb->proto_data; - *size = wbs->brush_size; - *color = wbs->brush_color; -} - -void silcpurple_wb_set_brush(PurpleWhiteboard *wb, int size, int color) -{ - SilcPurpleWb wbs = wb->proto_data; - 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 = wb->proto_data; - SilcBuffer packet; - int len; - PurpleConnection *gc; - SilcPurple sg; - - gc = purple_account_get_connection(wb->account); - g_return_if_fail(gc); - sg = gc->proto_data; - 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, - packet->head, len, TRUE); - } else if (wbs->type == 1) { - /* Channel message */ - silc_client_send_channel_message(sg->client, sg->conn, - wbs->u.channel, NULL, - SILC_MESSAGE_FLAG_DATA, - packet->head, len, TRUE); - } - - silc_buffer_free(packet); -} diff -r 0cc718e10344 -r 4f2d99bcb195 libpurple/protocols/silc10/wb.h --- a/libpurple/protocols/silc10/wb.h Mon Aug 22 06:32:44 2011 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - - silcpurple.h - - Author: Pekka Riikonen - - 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 SILCPURPLE_WB_H -#define SILCPURPLE_WB_H - -#include "silcpurple.h" -#include "whiteboard.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 /* SILCPURPLE_WB_H */