pidgin: d80abd35: Remove silc10
markdoliner at pidgin.im
markdoliner at pidgin.im
Mon Aug 22 03:07:24 EDT 2011
----------------------------------------------------------------------
Revision: d80abd35956ecd359432f347478ada213ce59fdc
Parent: 25abd21662b445023be41dbf93d6bbf9ccbbdea9
Author: markdoliner at pidgin.im
Date: 08/22/11 03:01:27
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/d80abd35956ecd359432f347478ada213ce59fdc
Changelog:
Remove silc10
Changes against parent 25abd21662b445023be41dbf93d6bbf9ccbbdea9
dropped libpurple/protocols/silc10
dropped libpurple/protocols/silc10/Makefile.am
dropped libpurple/protocols/silc10/Makefile.mingw
dropped libpurple/protocols/silc10/README
dropped libpurple/protocols/silc10/TODO
dropped libpurple/protocols/silc10/buddy.c
dropped libpurple/protocols/silc10/chat.c
dropped libpurple/protocols/silc10/ft.c
dropped libpurple/protocols/silc10/ops.c
dropped libpurple/protocols/silc10/pk.c
dropped libpurple/protocols/silc10/silc.c
dropped libpurple/protocols/silc10/silcpurple.h
dropped libpurple/protocols/silc10/util.c
dropped libpurple/protocols/silc10/wb.c
dropped libpurple/protocols/silc10/wb.h
patched configure.ac
patched libpurple/protocols/Makefile.am
-------------- next part --------------
============================================================
--- libpurple/protocols/Makefile.am ab2184b862c4cebb91e062b478a7f2e3fff18cd6
+++ libpurple/protocols/Makefile.am a1ab1fb5f8aec812d7956d21ec8c99b5242030c2
@@ -1,5 +1,5 @@ EXTRA_DIST = Makefile.mingw
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)
============================================================
--- configure.ac ea721cbc321ec33dd5de8c4f7c13626375ce0e6e
+++ configure.ac e2d544e11c017d658d68bc34a97322d878f89896
@@ -941,25 +941,6 @@ if test "x$silc_manual_check" = "xno"; t
], [
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 @@ else
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 @@ if test "x$silcclient" = "xyes"; then
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 <silcincludes.h>
-#include <silcmime.h>
- ]], [[]])], [
- 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,11 +1079,8 @@ if test "x$silcincludes" != "xyes" -o "x
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/'`
+ STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/silc//'`
fi
-if test "x$silc10includes" != "xyes" -o "x$silc10client" != "xyes"; then
- STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/silc10//'`
-fi
AC_SUBST(STATIC_PRPLS)
STATIC_LINK_LIBS=
extern_init=
@@ -1150,8 +1103,6 @@ for i in $STATIC_PRPLS ; do
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 @@ for i in $STATIC_PRPLS ; do
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,11 +1158,8 @@ if test "x$silcincludes" != "xyes" -o "x
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/'`
+ DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/silc//'`
fi
-if test "x$silc10includes" != "xyes" -o "x$silc10client" != "xyes"; then
- DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/silc10//'`
-fi
AC_SUBST(DYNAMIC_PRPLS)
for i in $DYNAMIC_PRPLS ; do
case $i in
@@ -1230,7 +1177,6 @@ for i in $DYNAMIC_PRPLS ; do
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 @@ AC_CONFIG_FILES([Makefile
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
============================================================
--- libpurple/protocols/silc10/Makefile.am 62d8f3edb8604438593e88835e3771e2216e4494
+++ /dev/null
@@ -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)
============================================================
--- libpurple/protocols/silc10/Makefile.mingw f219fe0aab6ec6bf4ec6f16c81171f454e58234f
+++ /dev/null
@@ -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)
============================================================
--- libpurple/protocols/silc10/README a7b22f8decde0cf4452bc5e0120a5e75f66e1742
+++ /dev/null
@@ -1,31 +0,0 @@
-SILC Purple Plugin
-==================
-
-This is the Purple protocol plugin of the protocol called Secure Internet
-Live Conferencing (SILC). The implementation will use the SILC Toolkit,
-freely available from the http://silcnet.org/ site, for the actual SILC
-protocol implementation.
-
-To include SILC into Purple, one needs to first compile and install
-the SILC Toolkit. It is done as follows:
-
- ./configure --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.
============================================================
--- libpurple/protocols/silc10/TODO 57cfee1a25c3e40913b14c20957856f527ad2d20
+++ /dev/null
@@ -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
-
============================================================
--- libpurple/protocols/silc10/buddy.c e8fabb3da669b214cd4a70cafc1f78657d1af639
+++ /dev/null
@@ -1,1748 +0,0 @@
-/*
-
- silcpurple_buddy.c
-
- Author: Pekka Riikonen <priikone at silcnet.org>
-
- 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
============================================================
--- libpurple/protocols/silc10/chat.c 25959233db7fff02b81c4d31d1d63f271814695e
+++ /dev/null
@@ -1,1456 +0,0 @@
-/*
-
- silcpurple_chat.c
-
- Author: Pekka Riikonen <priikone at silcnet.org>
-
- 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, _("<b>Channel Name:</b> %s"), tmp2);
- g_free(tmp2);
- if (channel->user_list && silc_hash_table_count(channel->user_list))
- g_string_append_printf(s, _("<br><b>User Count:</b> %d"),
- (int)silc_hash_table_count(channel->user_list));
-
- silc_hash_table_list(channel->user_list, &htl);
- while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
- if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) {
- tmp2 = g_markup_escape_text(chu->client->nickname, -1);
- g_string_append_printf(s, _("<br><b>Channel Founder:</b> %s"),
- tmp2);
- g_free(tmp2);
- break;
- }
- }
- silc_hash_table_list_reset(&htl);
-
- if (channel->channel_key)
- g_string_append_printf(s, _("<br><b>Channel Cipher:</b> %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, _("<br><b>Channel HMAC:</b> %s"),
- silc_hmac_get_name(channel->hmac));
-
- if (channel->topic) {
- tmp2 = g_markup_escape_text(channel->topic, -1);
- g_string_append_printf(s, _("<br><b>Channel Topic:</b><br>%s"), tmp2);
- g_free(tmp2);
- }
-
- if (channel->mode) {
- g_string_append_printf(s, _("<br><b>Channel Modes:</b> "));
- silcpurple_get_chmode_string(channel->mode, tmp, sizeof(tmp));
- g_string_append(s, tmp);
- }
-
- if (channel->founder_key) {
- char *fingerprint, *babbleprint;
- unsigned char *pk;
- SilcUInt32 pk_len;
- pk = silc_pkcs_public_key_encode(channel->founder_key, &pk_len);
- fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
- babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
-
- g_string_append_printf(s, _("<br><b>Founder Key Fingerprint:</b><br>%s"), fingerprint);
- g_string_append_printf(s, _("<br><b>Founder Key Babbleprint:</b><br>%s"), babbleprint);
-
- silc_free(fingerprint);
- silc_free(babbleprint);
- silc_free(pk);
- }
-
- 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 <I>%s</I>"),
- channel->channel_name);
- else
- g_snprintf(tmp, sizeof(tmp),
- _("Channel founder on <I>%s</I> is <I>%s</I>"),
- channel->channel_name, chu->client->nickname);
-
- purple_conversation_write(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;
- }
-}
============================================================
--- libpurple/protocols/silc10/ft.c 3b328ce851a002a35c3557253091202558a6fb94
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
-
- silcpurple_ft.c
-
- Author: Pekka Riikonen <priikone at silcnet.org>
-
- 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);
-}
============================================================
--- libpurple/protocols/silc10/ops.c 82ea63c073d9c3c565410665b9a083b87667c514
+++ /dev/null
@@ -1,2063 +0,0 @@
-/*
-
- silcpurple_ops.c
-
- Author: Pekka Riikonen <priikone at silcnet.org>
-
- 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), "<IMG ID=\"%d\">", imgid);
-
- if (channel)
- serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)),
- sender->nickname ?
- sender->nickname :
- "<unknown>", cflags,
- tmp, time(NULL));
- else
- serv_got_im(gc, sender->nickname ?
- sender->nickname : "<unknown>",
- 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 : "<unknown>", 0,
- tmp, time(NULL));
- g_free(tmp);
- g_free(msg);
- return;
- }
-
- if (flags & SILC_MESSAGE_FLAG_NOTICE) {
- msg = g_strdup_printf("(notice) <I>%s</I> %s",
- sender->nickname ?
- sender->nickname : "<unknown>",
- (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 : "<unknown>", 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 : "<unknown>",
- tmp, 0, time(NULL));
- g_free(msg);
- g_free(tmp);
- return;
- }
-
- if (flags & SILC_MESSAGE_FLAG_NOTICE && convo) {
- msg = g_strdup_printf("(notice) <I>%s</I> %s",
- sender->nickname ?
- sender->nickname : "<unknown>",
- (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 : "<unknown>",
- 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 <I>%s</I> 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 <I>%s</I> 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 <I>%s</I> 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),
- _("<I>%s</I> set channel <I>%s</I> modes to: %s"), name,
- channel->channel_name, buf2);
- } else {
- g_snprintf(buf, sizeof(buf),
- _("<I>%s</I> removed all channel <I>%s</I> modes"), name,
- channel->channel_name);
- }
- purple_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),
- _("<I>%s</I> set <I>%s's</I> 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),
- _("<I>%s</I> removed all <I>%s's</I> 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 <I>%s</I> by <I>%s</I> (%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
-};
============================================================
--- libpurple/protocols/silc10/pk.c 19d7a910dd14b60a0812e7e7b0c807e93cf17060
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
-
- silcpurple_pk.c
-
- Author: Pekka Riikonen <priikone at silcnet.org>
-
- 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);
- }
-}
============================================================
--- libpurple/protocols/silc10/silc.c b2177d246a0a86caddb0efae076a22ffc62cbe0a
+++ /dev/null
@@ -1,1965 +0,0 @@
-/*
-
- silcpurple.c
-
- Author: Pekka Riikonen <priikone at silcnet.org>
-
- 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 <I>%s</I> 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);
============================================================
--- libpurple/protocols/silc10/silcpurple.h 74b30a75cfad806a9e650d75fe9fe7b9ffe8a79b
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
-
- silcpurple.h
-
- Author: Pekka Riikonen <priikone at silcnet.org>
-
- 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 */
============================================================
--- libpurple/protocols/silc10/util.c acfacc250c29147ad966e5d4986ad5350ab7f555
+++ /dev/null
@@ -1,776 +0,0 @@
-/*
-
- silcpurple_util.c
-
- Author: Pekka Riikonen <priikone at silcnet.org>
-
- 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 */
============================================================
--- libpurple/protocols/silc10/wb.c 4685fa59f4a0d910948906f36cd156ab86447264
+++ /dev/null
@@ -1,520 +0,0 @@
-/*
-
- wb.c
-
- Author: Pekka Riikonen <priikone at silcnet.org>
-
- Copyright (C) 2005 Pekka Riikonen
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
-*/
-
-#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);
-}
============================================================
--- libpurple/protocols/silc10/wb.h 8f3b9c7db409b9756e158f023cf955184e6e8786
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-
- silcpurple.h
-
- Author: Pekka Riikonen <priikone at silcnet.org>
-
- Copyright (C) 2005 Pekka Riikonen
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
-*/
-
-#ifndef 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 */
More information about the Commits
mailing list